Imenovanja u Java okruženju: Difference between revisions
Created page with "Test prve strane" |
No edit summary |
||
| (63 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
{{abstract|min=8|txt=Konvencije o imenovanju čine programe razumljivijim tako što ih čine lakšim za čitanje. One takođe mogu pružiti informacije o funkciji identifikatora - na primer, da li je u pitanju konstanta, paket ili klasa - što može biti od pomoći u razumevanju koda.<br> | |||
'''Obavezno pročitati i pridržavati se.'''}} | |||
== Opšta pravila == | |||
* '''Koristimo engleski jezik''' – svi nazivi moraju biti na engleskom | |||
* '''Deskripcija obavezna''' – naziv treba jasno da opisuje šta klasa/metoda radi | |||
* '''Izbegavanje skraćenica''' – osim opštih (ID, DTO, URL, HTTP) | |||
* '''Izbegavati nepotrebne reči''' – izbeći dodavanje (myClass, TheClass) | |||
'''<big>Case Konvencije</big>''' | |||
* PascalCase (UpperCamelCase) – UserService, AuthenticationController | |||
* camelCase (lowerCamelCase) – userName, calculateTotal | |||
* lowercase – com.balans.auth.controllers, com.balans.auth.services | |||
* SCREAMING_SNAKE_CASE – MAX_LOGIN_ATTEMPTS, TOKEN_EXPIRY_DURATION | |||
== Dužina imenovanja == | |||
{|style="width:100%;" class="mst mst-siva" | |||
|- | |||
! Element !! Idealno (cilj) !! Gornja granica !! Napomene | |||
|- | |||
| Naziv paketa || 1-3 kratka segmenta || 4-5 segmenata || com.balans.auth.services; izbegavati dublje hijerarhije | |||
|- | |||
| Klasa/Interfejs || ≤ 20-25 karaktera || ≤ 40-50 || AuthenticationService; CgaBulkOperationService ➜ CgaBulkService | |||
|- | |||
| Metoda || ≤ 20-30 karaktera || ≤ 50-60 || Glagol + objekat: findByUsername, issueFirmToken | |||
|- | |||
| Varijabla || ≤ 15-20 karaktera || ≤ 30 || Kratko i jasno: attemptCount, accessibleFirms | |||
|- | |||
| Konstanta || ≤ 25-30 karaktera || ≤ 40-50 || TOKEN_EXPIRY_DURATION, MAX_LOGIN_ATTEMPTS | |||
|} | |||
'''<big><big>Kako odlučiti o dužini ?</big></big>''' | |||
'''<big>1. Ime mora biti jasno definisano da svako ko prvi put uđe u kod može da razume o čemu se radi.</big>''' | |||
'''<big>2. Ako klasa već daje kontekst, skraćuj metode i varijable</big>''' | |||
'''Primeri'''<br> | |||
'''U UserService klasi''' | |||
<div class="mkods"> | |||
public class UserService {<br /> | |||
<span class="mkods2" />public User create(CreateUserRequest request) { } - <span class="mkodit">Ne treba 'createUser'</span><br /> | |||
<span class="mkods2" />public void updateEmail(Long id, String email) { } - <span class="mkodit">Jasno je da je User</span><br /> | |||
} | |||
</div> | |||
'''U generičkim utility klasama''' | |||
<div class="mkods"> | |||
public class DatabaseUtils {<br /> | |||
<span class="mkods2" />public User createUser(UserData data) { } - <span class="mkodit">Treba 'User' za jasnoću</span><br /> | |||
<span class="mkods2" />public Group createGroup(GroupData data) { } - <span class="mkodit">Specifično</span><br /> | |||
} | |||
</div> | |||
'''<big>3. Ako metoda zahteva više od 3-4 reči, razmisli o:</big>''' | |||
* Korišćenju parametara/DTO objekta | |||
* Refaktorisanju klase | |||
'''Primeri'''<br> | |||
'''LOŠE - Predugačko''' | |||
<pre class='pogresno'> | |||
public List<User> findAllActiveUsersWithAccessToFirmByGroupId(Integer groupId, Integer firmId) { } | |||
</pre> | |||
'''DOBRO - Kraće, sa DTO parametrom''' | |||
<pre class='ispravno'> | |||
public List<User> findActiveUsers(UserSearchCriteria criteria) { } | |||
</pre> | |||
'''<big>4. Izbegavati nedefinsane pojmove kao Manager, Helper, Util, Data, Info</big>''' | |||
<code>public class UserDataManager</code> – <span class="mkodit">Šta je Data? Šta je Manager?</span> | |||
<code>public class UserInfo { }</code> – <span class="mkodit">Zašto ne samo User?</span> | |||
'''<big>5. Izražavanje</big>''' | |||
'''Loše''' | |||
<pre class='pogresno'> | |||
public void processData() {} | |||
public void handleRequest() {} | |||
</pre> | |||
'''Dobro''' | |||
<pre class='ispravno'> | |||
public void selectFirm() {} | |||
public void issueClusterToken() {} | |||
</pre> | |||
'''Refaktorisanje primer''' | |||
<pre> | |||
public class CgaBulkOperationService {} ➜ public class CgaBulkService {} | |||
</pre> | |||
== Tretiranje akronima == | |||
'''Akronimi u klasama i intefejsima (PascalCase)''' | |||
'''Dobro''' | |||
<pre class='ispravno'> | |||
public class JwtService {} | |||
public class HttpClient {} | |||
</pre> | |||
'''Loše''' | |||
<pre class='pogresno'> | |||
public class JWTService | |||
public class HTTPClient | |||
</pre> | |||
'''Akronimi u metodama i varijablama (camelCase)''' | |||
'''Dobro''' | |||
<pre class='ispravno'> | |||
private String jwtToken; | |||
private Integer httpStatus; | |||
public void parseXml() { } | |||
public String getApiKey() { } | |||
private Long userId; | |||
private String xmlContent; | |||
</pre> | |||
'''Loše''' | |||
<pre class='pogresno'> | |||
private String JWTToken; | |||
private Integer HTTPStatus; | |||
private Long userID; | |||
private String XMLContent; | |||
</pre> | |||
'''Imenovanje u konstantama i enum članovima''' | |||
<pre> | |||
public static final String JWT_SECRET = "secret"; | |||
public static final int HTTP_OK = 200; | |||
public static final String API_VERSION = "v1"; | |||
public static final String XML_HEADER = "<?xml version=\"1.0\"?>"; | |||
</pre> | |||
<pre> | |||
public enum TokenType { | |||
JWT, | |||
OAUTH, | |||
API_KEY | |||
} | |||
</pre> | |||
<pre> | |||
public static final String JWT_TOKEN_PREFIX = "Bearer"; | |||
public static final int HTTP_401_UNAUTHORIZED = 401; | |||
</pre> | |||
'''Specijalni slučajevi sa više akronima'''<br> | |||
'''Dobro''' | |||
<pre class='ispravno'> | |||
public class HttpApiClient { } | |||
public class XmlHttpParser { } | |||
</pre> | |||
'''Loše''' | |||
<pre class='pogresno'> | |||
public class HTTPAPIClient { } | |||
public class XMLHTTPParser { } | |||
</pre> | |||
'''Primer Akronima iz Auth servisa''' | |||
{| class="mst mst-siva" style="table-layout: fixed; width: 100%;" | |||
! Akronim !! Klasa/Interfejs !! Metoda/Varijabla !! Konstanta | |||
|- | |||
| API || ApiGateway || apiKey || API_VERSION | |||
|- | |||
| CBA || CbaSession || cbaEvent || CBA_VERSION | |||
|- | |||
| CGA || CgaService || cgaUserId || CGA_ROLE | |||
|- | |||
| CSA || CsaResource || csaToken || CSA_ROLE | |||
|- | |||
| DTO || UserDto || userDto || DTO_VERSION | |||
|- | |||
| HTTP || HttpClient || httpStatus || HTTP_OK | |||
|- | |||
| ID || UserId || userId || USER_ID | |||
|- | |||
| JSON || JsonParser || jsonContent || JSON_TYPE | |||
|- | |||
| JWT || JwtService || jwtToken || JWT_SECRET | |||
|- | |||
| SQL || SqlQuery || sqlStatement || SQL_TIMEOUT | |||
|- | |||
| URL || UrlBuilder || apiUrl || BASE_URL | |||
|- | |||
| XML || XmlParser || xmlDocument || XML_HEADER | |||
|} | |||
== Klase i interfejsi == | |||
'''<big>Klase (Classes)</big>'''<br> | |||
'''Imenovanje'''<br> | |||
* PascalCase format | |||
* Imenica ili imenička fraza | |||
* Jasno opisuje šta klasa predstavlja | |||
'''Osnovne klase''' | |||
'''Dobro'''<br> | |||
<pre class='ispravno'> | |||
public class User { } | |||
public class LoginRequest { } | |||
public class SessionService { } | |||
public class AuthenticationException { } | |||
</pre> | |||
'''Loše'''<br> | |||
<pre class='pogresno'> | |||
public class user { } | |||
public class Usr { } | |||
public class MyUser { } | |||
public class UserClass { } | |||
</pre> | |||
'''Sufiksi po tipu klase'''<br> | |||
'''Entity Classes''' (JPA/Domain models): | |||
<pre> | |||
public class User { } | |||
public class Group { } | |||
public class CbaSession { } | |||
public class Firm { } | |||
</pre> | |||
'''Service Classes''' - logika: | |||
<pre> | |||
public class AuthenticationService { } | |||
public class SessionService { } | |||
public class GroupService { } | |||
public class CgaBulkOperationService { } | |||
</pre> | |||
'''Controller/Resource Classes''' - REST endpoints: | |||
<pre> | |||
public class AuthController { } | |||
public class UserResource { } | |||
public class GroupResource { } | |||
public class CgaOperationsResource { } | |||
</pre> | |||
{{iPoruka|txt=U Melany Software koristimo Quarkus framework. | |||
Ako posmatramo arhitekturu, ''Controller'' u Springu odgovara ''Resource'' u Quarkusu. | |||
Zato koristimo isključivo termin '''''Resource'''''.|naslov=Resource vs Controller:}} | |||
'''DTO Classes''' - Data Transfer Objects: | |||
<pre> | |||
public class LoginRequest { } | |||
public class LoginResponse { } | |||
public class SelectFirmRequest { } | |||
public class BulkUserCreateRequest { } | |||
</pre> | |||
'''Exception Classes''' - Izuzeci: | |||
<pre> | |||
public class AuthenticationException { } | |||
public class UserLockedException { } | |||
public class FirmAccessException { } | |||
public class TenantDatabaseException { } | |||
</pre> | |||
'''Repository Classes''' (ako koristite Repository pattern): | |||
<pre> | |||
public class UserRepository { } | |||
public class GroupRepository { } | |||
</pre> | |||
'''Utility Classes''' - Pomoćne klase: | |||
<pre> | |||
public class PasswordEncoder { } | |||
public class JwtService { } | |||
public class StringUtils { } | |||
public class DateUtils { } | |||
</pre> | |||
'''<big>Interfejsi (Interfaces)</big>'''<br> | |||
'''Imenovanje - Dva Pristupa'''<br> | |||
'''Pristup 1: Bez prefiksa/sufiksa ''' | |||
'''Čist naziv''' | |||
<pre> | |||
public interface UserService { } | |||
public interface Repository<T> { } | |||
public interface Validator { } | |||
</pre> | |||
'''Implementacije koriste deskriptivne nazive''' | |||
<pre> | |||
public class DefaultUserService implements UserService { } | |||
public class UserServiceImpl implements UserService { } - Samo ako nema bolji naziv | |||
public class JpaRepository<T> implements Repository<T> { } | |||
</pre> | |||
{{pPoruka|txt=Izbegavaj ''Impl'' suffix ako možeš dati deskriptivniji naziv implementaciji|naslov=Preporuka:}} | |||
== Metode == | |||
'''<big>1. Osnovne konvencije</big>'''<br> | |||
'''Format: camelCase (počinje malim slovom)'''<br> | |||
'''Stil: glagol ili glagolska fraza'''<br> | |||
<pre> | |||
public void login() { } | |||
public User findUserByUsername(String username) { } | |||
public boolean isValid() { } | |||
public List<Firm> getAccessibleFirms() { } | |||
public void Login() { } | |||
public User user(String username) { } | |||
public boolean valid() { } | |||
public List<Firm> firms() { } | |||
</pre> | |||
'''<big>2. Standardni prefiksi</big>'''<br> | |||
'''Getter metode — get''' | |||
<pre> | |||
public String getUsername() { } | |||
public Integer getFirmId() { } | |||
public List<Group> getGroups() { } | |||
public LocalDateTime getCreatedAt() { } | |||
Boolean getteri koriste is/has/can: | |||
public boolean isActive() { } | |||
public boolean isLocked() { } | |||
public boolean hasAccess() { } | |||
public boolean canAccess() { } | |||
public boolean getActive() { } | |||
</pre> | |||
'''Setter metode — set''' | |||
<pre> | |||
public void setUsername(String username) { } | |||
public void setActive(boolean active) { } | |||
public void setGroupIds(List<Integer> groupIds) { } | |||
</pre> | |||
'''Query/Find metode''' | |||
<pre> | |||
public User findByUsername(String username) { } | |||
public List<User> findByGroupId(Integer groupId) { } | |||
public Optional<User> findById(Long id) { } | |||
public List<User> findAll() { } | |||
public Page<User> findAllByStatus(Integer status, Pageable pageable) { } | |||
</pre> | |||
'''Check/Validation metode''' | |||
<pre> | |||
public boolean exists(Long id) { } | |||
public boolean existsByUsername(String username) { } | |||
public void validate(LoginRequest request) { } | |||
public void validatePassword(String password) { } | |||
public boolean isPasswordValid(String password) { } | |||
</pre> | |||
'''Create/Save metode''' | |||
<pre> | |||
public User create(User user) { } | |||
public User save(User user) { } | |||
public void persist(User user) { } | |||
public User createUser(CreateUserRequest request) { } | |||
</pre> | |||
'''Update metode''' | |||
<pre> | |||
public User update(User user) { } | |||
public User updateEmail(Long userId, String newEmail) { } | |||
public void updateStatus(Long userId, Integer status) { } | |||
</pre> | |||
'''Delete metode''' | |||
<pre> | |||
public void delete(Long id) { } | |||
public void deleteById(Long id) { } | |||
public void deactivate(Long id) { } | |||
public void softDelete(Long id) { } | |||
</pre> | |||
'''Count metode''' | |||
<pre> | |||
public long count() { } | |||
public long countByStatus(Integer status) { } | |||
public int countActiveUsers() { } | |||
</pre> | |||
'''Build/Generate metode''' | |||
<pre> | |||
public String buildToken(User user) { } | |||
public String generatePassword() { } | |||
public String generateSessionId() { } | |||
public User buildUser(UserData data) { | |||
</pre> | |||
'''Convert/Transform metode''' | |||
<pre> | |||
public UserResponse toResponse(User user) { } | |||
public User toEntity(UserRequest request) { } | |||
@Override public String toString() { } | |||
public List<Integer> parseGroupIds(String groupIdString) { } | |||
</pre> | |||
'''Calculate metode''' | |||
<pre> | |||
public BigDecimal calculateTotal() { } | |||
public int calculateAge(LocalDate birthDate) { } | |||
public Duration calculateDuration(LocalDateTime start, LocalDateTime end) { } | |||
</pre> | |||
== Varijable i konstante == | |||
'''<big>1. Lokalne varijable i parametri</big>'''<br> | |||
'''Format: camelCase'''<br /> | |||
'''stil: imenica koja opisuje podatak'''<br /> | |||
'''Dobro'''<br /> | |||
<pre class='ispravno'> | |||
String username; | |||
Integer userId; | |||
List<Firm> availableFirms; | |||
LocalDateTime createdAt; | |||
boolean isActive. | |||
</pre> | |||
'''Loše'''<br /> | |||
<pre class='pogresno'> | |||
String Username; | |||
String usr; | |||
String strUsername; | |||
String user_name. | |||
</pre> | |||
'''<big>Česte konvencije:</big>'''<br> | |||
'''ID varijable'''<br /> | |||
<pre> | |||
Long userId; | |||
Integer firmId; | |||
Long accountId. | |||
</pre> | |||
'''Kolekcije (uvek množina)'''<br /> | |||
<pre> | |||
List<User> users; | |||
Set<Integer> firmIds; | |||
Map<String, User> userMap. | |||
</pre> | |||
'''Boolean varijable (pitanje ili stanje)'''<br /> | |||
<pre> | |||
boolean isActive; | |||
boolean hasAccess; | |||
boolean canDelete; | |||
boolean shouldValidate. | |||
</pre> | |||
'''DTO/Request objekti'''<br /> | |||
<pre> | |||
LoginRequest loginRequest; | |||
CreateUserRequest createRequest; | |||
BulkUserCreateRequest bulkRequest. | |||
</pre> | |||
'''Response objekti'''<br /> | |||
<pre> | |||
LoginResponse loginResponse; | |||
UserResponse userResponse. | |||
</pre> | |||
'''<big>2. Instance varijable (fields)</big>'''<br> | |||
'''Dobro'''<br /> | |||
<pre class='ispravno'>public class User { | |||
private Long accId; | |||
private String username; | |||
private String email; | |||
private Integer roleType; | |||
private LocalDateTime createdAt; | |||
private List<Integer> groupIds; | |||
}</pre> | |||
'''Loše'''<br /> | |||
<pre class='pogresno'>public class User { | |||
private Long AccId; | |||
private String _username; | |||
private String m_email; | |||
private Integer role_type; | |||
}</pre> | |||
'''<big>3. Static final konstante</big>'''<br> | |||
'''Format: SCREAMING_SNAKE_CASE'''<br /> | |||
'''Dobro'''<br /> | |||
<pre class='ispravno'> | |||
public static final int MAX_LOGIN_ATTEMPTS = 5; | |||
public static final String DEFAULT_ROLE = "USER"; | |||
public static final Duration TOKEN_EXPIRY_DURATION = Duration.ofHours(24); | |||
public static final String JWT_ISSUER = "balans"; | |||
</pre> | |||
'''Loše'''<br /> | |||
<pre class='pogresno'> | |||
public static final int maxLoginAttempts = 5; | |||
public static final int max_attempts = 5; | |||
public static final String defaultRole = "USER"; | |||
</pre> | |||
'''<big>Konvencije za konstante</big>'''<br> | |||
'''HTTP status''' | |||
<pre>public static final int STATUS_OK = 200; | |||
public static final int STATUS_UNAUTHORIZED = 401;</pre> | |||
'''DB status''' | |||
<pre>public static final int STATUS_ACTIVE = 0; | |||
public static final int STATUS_INACTIVE = 1; | |||
public static final int STATUS_LOCKED = 2;</pre> | |||
'''Role type''' | |||
<pre>public static final int ROLE_USER = 0; | |||
public static final int ROLE_CGA = 1; | |||
public static final int ROLE_CSA = 2;</pre> | |||
'''Token types''' | |||
<pre>public static final String TOKEN_TYPE_CLUSTER = "CLUSTER"; | |||
public static final String TOKEN_TYPE_FIRM = "FIRM";</pre> | |||
'''Error codes''' | |||
<pre>public static final String ERROR_AUTH_INVALID = "AUTH_INVALID"; | |||
public static final String ERROR_USER_LOCKED = "USER_LOCKED";</pre> | |||
'''Delimiter konstante''' | |||
<pre>public static final String GROUP_DELIMITER = ","; | |||
public static final String FIRM_DELIMITER = ",";</pre> | |||
'''<big>4. Enum konstante</big>'''<br> | |||
'''Format: SCREAMING_SNAKE_CASE''' | |||
<pre> | |||
public enum TokenType { | |||
CLUSTER, | |||
FIRM, | |||
ARCHIVE | |||
} | |||
</pre> | |||
<pre> | |||
public enum UserStatus { | |||
ACTIVE, | |||
INACTIVE, | |||
LOCKED | |||
} | |||
</pre> | |||
<pre> | |||
public enum RoleType { | |||
USER, | |||
CGA, | |||
CSA | |||
} | |||
</pre> | |||
<pre> | |||
public enum HttpStatus { | |||
OK(200), | |||
UNAUTHORIZED(401), | |||
FORBIDDEN(403); | |||
private final int code; | |||
HttpStatus(int code) { this.code = code; } | |||
public int getCode() { return code; } | |||
} | |||
</pre> | |||
== Paketi == | |||
'''<big>1. Osnovne konvencije</big>''' | |||
'''Format: sva mala slova, bez underscore ili camelCase.'''<br> | |||
'''Struktura: obrnuti domen + aplikacija + modul.''' | |||
<div class="mkods"> | |||
<span class="ispravno"> | |||
package com.balans.auth.controllers;<br /> | |||
package com.balans.auth.services;<br /> | |||
package com.balans.auth.domain;<br /> | |||
package com.balans.auth.dto;<br /></span> | |||
<span class="pogresno"> | |||
package com.balans.auth.Controllers;<br /> | |||
package com.balans.auth.user_service;<br /> | |||
package com.balans.auth.userService; | |||
</span></div> | |||
'''<big>2. Standardna struktura paketa</big>''' | |||
<big>'''Root com.balans.auth'''</big> | |||
{|style="width:100%;" class="mst mst-snow" | |||
|- | |||
!Paket!!Svrha!!Tipične klase | |||
|- | |||
|com.balans.auth.controllers||HTTP endpoint-i (REST sloj)||AuthResource, UserResource | |||
|- | |||
|com.balans.auth.services||Poslovna logika i orkestracija||AuthenticationService, SessionService | |||
|- | |||
|com.balans.auth.domain||JPA/entiteti i domenski modeli||User, Group, CbaSession | |||
|- | |||
|com.balans.auth.dto||Ulazno/izlazni DTO objekti||LoginRequest, LoginResponse | |||
|- | |||
|com.balans.auth.exceptions||Domen-specifični izuzeci||AuthenticationException, UserLockedException | |||
|- | |||
|com.balans.auth.security||Bezbednosni utili i komponente||PasswordEncoder, JwtService | |||
|- | |||
|com.balans.auth.repositories||Pristup podacima (repo sloj)||UserRepository, GroupRepository | |||
|- | |||
|com.balans.auth.config||Konfiguracija modula i bean-ovi||AuthConfig, ObjectMapperConfig | |||
|} | |||
Latest revision as of 12:34, 14 November 2025
8 min |
Konvencije o imenovanju čine programe razumljivijim tako što ih čine lakšim za čitanje. One takođe mogu pružiti informacije o funkciji identifikatora - na primer, da li je u pitanju konstanta, paket ili klasa - što može biti od pomoći u razumevanju koda.
|
Opšta pravila
- Koristimo engleski jezik – svi nazivi moraju biti na engleskom
- Deskripcija obavezna – naziv treba jasno da opisuje šta klasa/metoda radi
- Izbegavanje skraćenica – osim opštih (ID, DTO, URL, HTTP)
- Izbegavati nepotrebne reči – izbeći dodavanje (myClass, TheClass)
Case Konvencije
- PascalCase (UpperCamelCase) – UserService, AuthenticationController
- camelCase (lowerCamelCase) – userName, calculateTotal
- lowercase – com.balans.auth.controllers, com.balans.auth.services
- SCREAMING_SNAKE_CASE – MAX_LOGIN_ATTEMPTS, TOKEN_EXPIRY_DURATION
Dužina imenovanja
| Element | Idealno (cilj) | Gornja granica | Napomene |
|---|---|---|---|
| Naziv paketa | 1-3 kratka segmenta | 4-5 segmenata | com.balans.auth.services; izbegavati dublje hijerarhije |
| Klasa/Interfejs | ≤ 20-25 karaktera | ≤ 40-50 | AuthenticationService; CgaBulkOperationService ➜ CgaBulkService |
| Metoda | ≤ 20-30 karaktera | ≤ 50-60 | Glagol + objekat: findByUsername, issueFirmToken |
| Varijabla | ≤ 15-20 karaktera | ≤ 30 | Kratko i jasno: attemptCount, accessibleFirms |
| Konstanta | ≤ 25-30 karaktera | ≤ 40-50 | TOKEN_EXPIRY_DURATION, MAX_LOGIN_ATTEMPTS |
Kako odlučiti o dužini ?
1. Ime mora biti jasno definisano da svako ko prvi put uđe u kod može da razume o čemu se radi.
2. Ako klasa već daje kontekst, skraćuj metode i varijable
Primeri
U UserService klasi
public class UserService {
public User create(CreateUserRequest request) { } - Ne treba 'createUser'
public void updateEmail(Long id, String email) { } - Jasno je da je User
}
U generičkim utility klasama
public class DatabaseUtils {
public User createUser(UserData data) { } - Treba 'User' za jasnoću
public Group createGroup(GroupData data) { } - Specifično
}
3. Ako metoda zahteva više od 3-4 reči, razmisli o:
- Korišćenju parametara/DTO objekta
- Refaktorisanju klase
Primeri
LOŠE - Predugačko
public List<User> findAllActiveUsersWithAccessToFirmByGroupId(Integer groupId, Integer firmId) { }
DOBRO - Kraće, sa DTO parametrom
public List<User> findActiveUsers(UserSearchCriteria criteria) { }
4. Izbegavati nedefinsane pojmove kao Manager, Helper, Util, Data, Info
public class UserDataManager – Šta je Data? Šta je Manager?
public class UserInfo { } – Zašto ne samo User?
5. Izražavanje
Loše
public void processData() {}
public void handleRequest() {}
Dobro
public void selectFirm() {}
public void issueClusterToken() {}
Refaktorisanje primer
public class CgaBulkOperationService {} ➜ public class CgaBulkService {}
Tretiranje akronima
Akronimi u klasama i intefejsima (PascalCase)
Dobro
public class JwtService {}
public class HttpClient {}
Loše
public class JWTService public class HTTPClient
Akronimi u metodama i varijablama (camelCase)
Dobro
private String jwtToken;
private Integer httpStatus;
public void parseXml() { }
public String getApiKey() { }
private Long userId;
private String xmlContent;
Loše
private String JWTToken; private Integer HTTPStatus; private Long userID; private String XMLContent;
Imenovanje u konstantama i enum članovima
public static final String JWT_SECRET = "secret"; public static final int HTTP_OK = 200; public static final String API_VERSION = "v1"; public static final String XML_HEADER = "<?xml version=\"1.0\"?>";
public enum TokenType {
JWT,
OAUTH,
API_KEY
}
public static final String JWT_TOKEN_PREFIX = "Bearer"; public static final int HTTP_401_UNAUTHORIZED = 401;
Specijalni slučajevi sa više akronima
Dobro
public class HttpApiClient { }
public class XmlHttpParser { }
Loše
public class HTTPAPIClient { }
public class XMLHTTPParser { }
Primer Akronima iz Auth servisa
| Akronim | Klasa/Interfejs | Metoda/Varijabla | Konstanta |
|---|---|---|---|
| API | ApiGateway | apiKey | API_VERSION |
| CBA | CbaSession | cbaEvent | CBA_VERSION |
| CGA | CgaService | cgaUserId | CGA_ROLE |
| CSA | CsaResource | csaToken | CSA_ROLE |
| DTO | UserDto | userDto | DTO_VERSION |
| HTTP | HttpClient | httpStatus | HTTP_OK |
| ID | UserId | userId | USER_ID |
| JSON | JsonParser | jsonContent | JSON_TYPE |
| JWT | JwtService | jwtToken | JWT_SECRET |
| SQL | SqlQuery | sqlStatement | SQL_TIMEOUT |
| URL | UrlBuilder | apiUrl | BASE_URL |
| XML | XmlParser | xmlDocument | XML_HEADER |
Klase i interfejsi
Klase (Classes)
Imenovanje
- PascalCase format
- Imenica ili imenička fraza
- Jasno opisuje šta klasa predstavlja
Osnovne klase
Dobro
public class User { }
public class LoginRequest { }
public class SessionService { }
public class AuthenticationException { }
Loše
public class user { }
public class Usr { }
public class MyUser { }
public class UserClass { }
Sufiksi po tipu klase
Entity Classes (JPA/Domain models):
public class User { }
public class Group { }
public class CbaSession { }
public class Firm { }
Service Classes - logika:
public class AuthenticationService { }
public class SessionService { }
public class GroupService { }
public class CgaBulkOperationService { }
Controller/Resource Classes - REST endpoints:
public class AuthController { }
public class UserResource { }
public class GroupResource { }
public class CgaOperationsResource { }
Ako posmatramo arhitekturu, Controller u Springu odgovara Resource u Quarkusu.
Zato koristimo isključivo termin Resource.
DTO Classes - Data Transfer Objects:
public class LoginRequest { }
public class LoginResponse { }
public class SelectFirmRequest { }
public class BulkUserCreateRequest { }
Exception Classes - Izuzeci:
public class AuthenticationException { }
public class UserLockedException { }
public class FirmAccessException { }
public class TenantDatabaseException { }
Repository Classes (ako koristite Repository pattern):
public class UserRepository { }
public class GroupRepository { }
Utility Classes - Pomoćne klase:
public class PasswordEncoder { }
public class JwtService { }
public class StringUtils { }
public class DateUtils { }
Interfejsi (Interfaces)
Imenovanje - Dva Pristupa
Pristup 1: Bez prefiksa/sufiksa
Čist naziv
public interface UserService { }
public interface Repository<T> { }
public interface Validator { }
Implementacije koriste deskriptivne nazive
public class DefaultUserService implements UserService { }
public class UserServiceImpl implements UserService { } - Samo ako nema bolji naziv
public class JpaRepository<T> implements Repository<T> { }
Metode
1. Osnovne konvencije
Format: camelCase (počinje malim slovom)
Stil: glagol ili glagolska fraza
public void login() { }
public User findUserByUsername(String username) { }
public boolean isValid() { }
public List<Firm> getAccessibleFirms() { }
public void Login() { }
public User user(String username) { }
public boolean valid() { }
public List<Firm> firms() { }
2. Standardni prefiksi
Getter metode — get
public String getUsername() { }
public Integer getFirmId() { }
public List<Group> getGroups() { }
public LocalDateTime getCreatedAt() { }
Boolean getteri koriste is/has/can:
public boolean isActive() { }
public boolean isLocked() { }
public boolean hasAccess() { }
public boolean canAccess() { }
public boolean getActive() { }
Setter metode — set
public void setUsername(String username) { }
public void setActive(boolean active) { }
public void setGroupIds(List<Integer> groupIds) { }
Query/Find metode
public User findByUsername(String username) { }
public List<User> findByGroupId(Integer groupId) { }
public Optional<User> findById(Long id) { }
public List<User> findAll() { }
public Page<User> findAllByStatus(Integer status, Pageable pageable) { }
Check/Validation metode
public boolean exists(Long id) { }
public boolean existsByUsername(String username) { }
public void validate(LoginRequest request) { }
public void validatePassword(String password) { }
public boolean isPasswordValid(String password) { }
Create/Save metode
public User create(User user) { }
public User save(User user) { }
public void persist(User user) { }
public User createUser(CreateUserRequest request) { }
Update metode
public User update(User user) { }
public User updateEmail(Long userId, String newEmail) { }
public void updateStatus(Long userId, Integer status) { }
Delete metode
public void delete(Long id) { }
public void deleteById(Long id) { }
public void deactivate(Long id) { }
public void softDelete(Long id) { }
Count metode
public long count() { }
public long countByStatus(Integer status) { }
public int countActiveUsers() { }
Build/Generate metode
public String buildToken(User user) { }
public String generatePassword() { }
public String generateSessionId() { }
public User buildUser(UserData data) {
Convert/Transform metode
public UserResponse toResponse(User user) { }
public User toEntity(UserRequest request) { }
@Override public String toString() { }
public List<Integer> parseGroupIds(String groupIdString) { }
Calculate metode
public BigDecimal calculateTotal() { }
public int calculateAge(LocalDate birthDate) { }
public Duration calculateDuration(LocalDateTime start, LocalDateTime end) { }
Varijable i konstante
1. Lokalne varijable i parametri
Format: camelCase
stil: imenica koja opisuje podatak
Dobro
String username; Integer userId; List<Firm> availableFirms; LocalDateTime createdAt; boolean isActive.
Loše
String Username; String usr; String strUsername; String user_name.
Česte konvencije:
ID varijable
Long userId; Integer firmId; Long accountId.
Kolekcije (uvek množina)
List<User> users; Set<Integer> firmIds; Map<String, User> userMap.
Boolean varijable (pitanje ili stanje)
boolean isActive; boolean hasAccess; boolean canDelete; boolean shouldValidate.
DTO/Request objekti
LoginRequest loginRequest; CreateUserRequest createRequest; BulkUserCreateRequest bulkRequest.
Response objekti
LoginResponse loginResponse; UserResponse userResponse.
2. Instance varijable (fields)
Dobro
public class User {
private Long accId;
private String username;
private String email;
private Integer roleType;
private LocalDateTime createdAt;
private List<Integer> groupIds;
}
Loše
public class User {
private Long AccId;
private String _username;
private String m_email;
private Integer role_type;
}
3. Static final konstante
Format: SCREAMING_SNAKE_CASE
Dobro
public static final int MAX_LOGIN_ATTEMPTS = 5; public static final String DEFAULT_ROLE = "USER"; public static final Duration TOKEN_EXPIRY_DURATION = Duration.ofHours(24); public static final String JWT_ISSUER = "balans";
Loše
public static final int maxLoginAttempts = 5; public static final int max_attempts = 5; public static final String defaultRole = "USER";
Konvencije za konstante
HTTP status
public static final int STATUS_OK = 200; public static final int STATUS_UNAUTHORIZED = 401;
DB status
public static final int STATUS_ACTIVE = 0; public static final int STATUS_INACTIVE = 1; public static final int STATUS_LOCKED = 2;
Role type
public static final int ROLE_USER = 0; public static final int ROLE_CGA = 1; public static final int ROLE_CSA = 2;
Token types
public static final String TOKEN_TYPE_CLUSTER = "CLUSTER"; public static final String TOKEN_TYPE_FIRM = "FIRM";
Error codes
public static final String ERROR_AUTH_INVALID = "AUTH_INVALID"; public static final String ERROR_USER_LOCKED = "USER_LOCKED";
Delimiter konstante
public static final String GROUP_DELIMITER = ","; public static final String FIRM_DELIMITER = ",";
4. Enum konstante
Format: SCREAMING_SNAKE_CASE
public enum TokenType {
CLUSTER,
FIRM,
ARCHIVE
}
public enum UserStatus {
ACTIVE,
INACTIVE,
LOCKED
}
public enum RoleType {
USER,
CGA,
CSA
}
public enum HttpStatus {
OK(200),
UNAUTHORIZED(401),
FORBIDDEN(403);
private final int code;
HttpStatus(int code) { this.code = code; }
public int getCode() { return code; }
}
Paketi
1. Osnovne konvencije
Format: sva mala slova, bez underscore ili camelCase.
Struktura: obrnuti domen + aplikacija + modul.
package com.balans.auth.controllers;
package com.balans.auth.services;
package com.balans.auth.domain;
package com.balans.auth.dto;
package com.balans.auth.Controllers;
package com.balans.auth.user_service;
package com.balans.auth.userService;
2. Standardna struktura paketa
Root com.balans.auth
| Paket | Svrha | Tipične klase |
|---|---|---|
| com.balans.auth.controllers | HTTP endpoint-i (REST sloj) | AuthResource, UserResource |
| com.balans.auth.services | Poslovna logika i orkestracija | AuthenticationService, SessionService |
| com.balans.auth.domain | JPA/entiteti i domenski modeli | User, Group, CbaSession |
| com.balans.auth.dto | Ulazno/izlazni DTO objekti | LoginRequest, LoginResponse |
| com.balans.auth.exceptions | Domen-specifični izuzeci | AuthenticationException, UserLockedException |
| com.balans.auth.security | Bezbednosni utili i komponente | PasswordEncoder, JwtService |
| com.balans.auth.repositories | Pristup podacima (repo sloj) | UserRepository, GroupRepository |
| com.balans.auth.config | Konfiguracija modula i bean-ovi | AuthConfig, ObjectMapperConfig |