AJ1 - Standard sviluppo JAVA/ANGULAR
Manuale Operativo
Stack: Java (Spring Boot) & TypeScript (Angular)
Questo documento definisce le regole immutabili per lo sviluppo del software gestionale aziendale. L'obiettivo è trasformare il codice in una risorsa aziendale leggibile da chiunque, non solo da chi l'ha scritto.
1. Naming Convention e Standard di Codifica (Dettagliato)
La coerenza nei nomi è la prima forma di documentazione. Di seguito le tabelle dettagliate per Backend e Frontend.
1.1 Backend: Java & Spring Boot
In Java, privilegiamo nomi descrittivi lunghi piuttosto che abbreviazioni criptiche.
| Elemento | Regola di Formattazione | Suffisso/Prefisso Obbligatorio | Esempio Corretto ✅ | Esempio Errato ❌ |
|---|---|---|---|---|
| Classi Generiche | PascalCase | Nessuno | InvoiceCalculator |
invoiceCalc, Invoice_Calculator |
| Interfacce | PascalCase | Nessun prefisso "I" | PaymentGateway |
IPaymentGateway, PaymentGatewayInterface |
| Classi di Implementazione | PascalCase | Suffisso Impl (solo se necessario) |
StripePaymentGateway (meglio) o PaymentGatewayImpl |
PaymentGatewayCode |
| Controller (API) | PascalCase | Suffisso Controller |
UserProfileController |
UserApis, ProfileHandler |
| Service (Business Logic) | PascalCase | Suffisso Service |
TaxCalculationService |
TaxManager, TaxBean |
| Repository (DB) | PascalCase | Suffisso Repository |
OrderRepository |
OrderDAO, OrderDb |
| Entity (JPA) | PascalCase | Nessuno (Nome Singolare) | CustomerOrder |
CustomerOrders, Tbl_Order |
| DTO (Data Transfer) | PascalCase | Suffisso DTO o Request/Response |
CreateUserRequest, UserSummaryDTO |
UserJson, UserData |
| Metodi | camelCase | Verbi imperativi | findActiveUsers(), calculateTotal() |
ActiveUsers(), calc() |
| Metodi Booleani | camelCase | Prefisso is, has, can, should |
isActive(), hasPermissions() |
checkActive(), getFlag() |
| Costanti | UPPER_SNAKE | Nessuno | MAX_LOGIN_ATTEMPTS |
maxLoginAttempts, ConstMaxLogin |
| Variabili Locali | camelCase | Nessuno | currentBalance |
tmp, val, cb |
| Generics | UpperChar | T, E, K, V | public class Wrapper<T> |
public class Wrapper<Type> |
| Test Classes | PascalCase | Suffisso Test |
OrderServiceTest |
TestOrderService |
1.2 Frontend: TypeScript & Angular
Angular ha standard molto specifici legati anche al file system.
| Elemento | Regola Codice | Regola File System (Nome File) | Esempio Codice ✅ | Esempio File ✅ |
|---|---|---|---|---|
| Component | PascalCase | kebab-case + .component.ts |
ProductListComponent |
product-list.component.ts |
| Service | PascalCase | kebab-case + .service.ts |
AuthService |
auth.service.ts |
| Interface/Model | PascalCase | kebab-case + .model.ts |
Employee (No "I" prefix) |
employee.model.ts |
| Pipe | camelCase (nome classe Pascal) | kebab-case + .pipe.ts |
@Pipe({name: 'currencyFormat'}) |
currency-format.pipe.ts |
| Directive | PascalCase | kebab-case + .directive.ts |
HighlightDirective |
highlight.directive.ts |
| Module | PascalCase | kebab-case + .module.ts |
InventoryModule |
inventory.module.ts |
| Observable | camelCase + $ |
N/A | products$, isLoading$ |
N/A |
| Subject/BehaviorSubject | camelCase + $ |
N/A | currentUser$ |
N/A |
| Costanti Globali | UPPER_SNAKE | kebab-case + .constants.ts |
API_TIMEOUT_MS |
app.constants.ts |
| Input (@Input) | camelCase | N/A | @Input() userName: string |
N/A |
| Output (@Output) | camelCase | N/A (Evitare prefisso 'on') | @Output() saved = new EventEmitter() |
N/A |
2. Principi SOLID applicati all'ERP
I principi SOLID non sono teoria accademica, ma strumenti pratici per evitare che il codice dell'ERP diventi "spaghetti code" dopo 6 mesi.
S - Single Responsibility Principle (SRP)
Una classe deve avere una sola ragione per cambiare.
- Java Spring:
- I Controller gestiscono solo HTTP (ricezione request, validazione input, risposta JSON). Non devono fare query al DB o calcoli.
- I Service contengono la logica di business.
- Esempio: Se devi cambiare il calcolo dell'IVA, devi toccare solo
TaxService, nonOrderController.
- Angular:
- Un Component gestisce solo la vista (UI).
- Tutte le chiamate HTTP e la gestione dello stato vanno delegate ai Service.
- Bad: Fare
this.http.get(...)dentrongOnInit. - Good: Fare
this.userService.getAll().subscribe(...).
O - Open/Closed Principle (OCP)
Le entità software devono essere aperte all'estensione, ma chiuse alla modifica.
- Scenario ERP: Calcolo sconti diverso per tipo cliente (VIP, Standard, New).
- Soluzione: Invece di un enorme
switchoif-elsenel codice che tocchi ogni volta che aggiungi un tipo cliente, usa il polimorfismo.- Crea un'interfaccia
DiscountStrategy. - Implementa
VipDiscount,StandardDiscount. - Spring inietterà la strategia corretta a runtime.
- Crea un'interfaccia
L - Liskov Substitution Principle (LSP)
Le sottoclassi devono essere sostituibili alle loro classi base senza rompere l'applicazione.
- Attenzione: Se estendi una classe ed esegui l'override di un metodo lanciando
NotImplementedExceptiono non facendo nulla, stai violando LSP. - Esempio: Se hai una classe
BaseUsere unaGuestUserche estende la base, maGuestUserlancia errore sugetProfile(), alloraGuestUsernon dovrebbe ereditare daBaseUser.
I - Interface Segregation Principle (ISP)
Meglio tante interfacce specifiche che un'unica interfaccia generica.
- Java: Evita un'interfaccia gigante
ErpOperationscon 200 metodi. Dividila inInvoicingOperations,InventoryOperations,UserOperations. - Angular: Quando crei modelli (interfacce) per i dati, non creare un singolo modello
Userche contiene tutto. Crea:UserSummary(per le liste, pochi campi).UserDetails(per la pagina profilo, tutti i campi).
D - Dependency Inversion Principle (DIP)
Dipendere dalle astrazioni, non dalle concrezioni.
- Spring Boot: È il cuore del framework.
- Mai fare:
private OrderService service = new OrderService(); - Sempre fare: Injection tramite costruttore.
- Mai fare:
- Angular:
- I componenti non devono sapere come viene recuperato un dato (se da REST API, GraphQL o LocalStorage). Devono solo chiedere al Service astratto.
3. Architettura e Pattern Specifici
Per garantire l'aderenza ai principi sopra esposti, utilizziamo un'architettura a livelli rigorosa.
[Image of Spring Boot Angular Architecture diagram]
3.1 Pattern nel Backend (Spring)
- Repository Pattern: Astrazione sull'accesso ai dati. Utilizzare
JpaRepository. Per query complesse, usareSpecificationo@Query, mai logica SQL dentro i Service. - DTO Pattern (Data Transfer Object):
- Il Service converte
Entity->DTOprima di restituire al Controller. - Librerie consigliate:
MapStruct(più performante) oModelMapper.
- Il Service converte
- Global Exception Handler: Usare
@ControllerAdviceper catturare errori comeEntityNotFoundExceptione restituire un JSON standard (es.{ code: 404, message: "Order not found" }).
3.2 Pattern nel Frontend (Angular)
- Smart & Dumb Components:
- Smart (Container): Pagine intere. Parlano con i Service.
- Dumb (Presentational): Pulsanti, tabelle, card. Ricevono dati via
@Input()ed emettono eventi via@Output(). Sono riutilizzabili ovunque.
- Module Lazy Loading: Ogni modulo funzionale dell'ERP (es. Magazzino, Contabilità) deve avere il proprio
routing.moduleed essere caricato solo quando l'utente ci clicca sopra.
4. Esempi Pratici e Schemi
Esempio di Nomenclatura e Clean Code (Java Service)
@Service
@RequiredArgsConstructor // Lombok per Dependency Injection (DIP)
public class InvoiceProcessingService { // PascalCase, Descrittivo
private final InvoiceRepository invoiceRepository; // camelCase
private final EmailNotificationService emailService;
// Metodo pubblico che orchestra il flusso
@Transactional
public void processOverdueInvoices() {
List<Invoice> overdueInvoices = invoiceRepository.findOverdueInvoices(LocalDate.now());
for (Invoice invoice : overdueInvoices) {
if (shouldSendReminder(invoice)) { // Estrazione logica in metodo privato (SRP)
sendReminder(invoice);
}
}
}
// Metodo booleano (Convenzione 'should', 'is')
private boolean shouldSendReminder(Invoice invoice) {
return invoice.getDaysOverdue() > 7 && !invoice.isReminderSent();
}
private void sendReminder(Invoice invoice) {
// Logica invio...
}
}
Esempio di Struttura File Angular
Una struttura disordinata uccide i progetti Angular. Usa questa struttura a cartelle:
src/
app/
core/ (Singleton services, Guards, Interceptors)
auth/
auth.service.ts
auth.guard.ts
interceptors/
shared/ (Componenti riutilizzabili importati ovunque)
components/
data-table/
alert-box/
pipes/
features/ (Moduli di business - Lazy Loaded)
inventory/
components/ (Dumb components specifici di modulo)
pages/ (Smart components/Pagine)
inventory-list/
inventory-list.component.ts
inventory-list.component.html
inventory.module.ts
inventory-routing.module.ts
accounting/
app.component.ts
Questa guida è da considerarsi vincolante per ogni Pull Request. Codice non conforme agli standard di nomenclatura o ai principi SOLID verrà respinto in fase di Code Review.
Nessun commento