Imenovanja u Java okruženju: Difference between revisions

10.11.2025 Uroš | 14.11.2025

Uroš (talk | contribs)
No edit summary
No edit summary
 
(61 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{abstract}}
{{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.'''}}




Test prve strane


== Opšta pravila ==
== Opšta pravila ==
zdsgr
* '''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 ==
== Dužina imenovanja ==
wrefwef
{|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 ==
== Tretiranje akronima ==
fghtfng
 
'''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 ==
== Klase i interfejsi ==
fgnfgn
'''<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 ==
== Metode ==
eeeeeeeeeeee
'''<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 ==
== Varijable i konstante ==
wwwwwwwwwwwwwwww
'''<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 ==
== Paketi ==
erfvsvsvrvr
'''<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>


== Primeri ==
{|style="width:100%;" class="mst mst-snow"
ryjgjmugdhmn
|-
!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.


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)

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 { }
Resource vs Controller:
U Melany Software koristimo Quarkus framework.

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> { }
Preporuka:
Izbegavaj Impl suffix ako možeš dati deskriptivniji naziv implementaciji


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