Passa al contenuto principale

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, non OrderController.
  • 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(...) dentro ngOnInit.
    • 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 switch o if-else nel 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.

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 NotImplementedException o non facendo nulla, stai violando LSP.
  • Esempio: Se hai una classe BaseUser e una GuestUser che estende la base, ma GuestUser lancia errore su getProfile(), allora GuestUser non dovrebbe ereditare da BaseUser.

I - Interface Segregation Principle (ISP)

Meglio tante interfacce specifiche che un'unica interfaccia generica.

  • Java: Evita un'interfaccia gigante ErpOperations con 200 metodi. Dividila in InvoicingOperations, InventoryOperations, UserOperations.
  • Angular: Quando crei modelli (interfacce) per i dati, non creare un singolo modello User che 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.
  • 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)

  1. Repository Pattern: Astrazione sull'accesso ai dati. Utilizzare JpaRepository. Per query complesse, usare Specification o @Query, mai logica SQL dentro i Service.
  2. DTO Pattern (Data Transfer Object):
    • Il Service converte Entity -> DTO prima di restituire al Controller.
    • Librerie consigliate: MapStruct (più performante) o ModelMapper.
  3. Global Exception Handler: Usare @ControllerAdvice per catturare errori come EntityNotFoundException e restituire un JSON standard (es. { code: 404, message: "Order not found" }).

3.2 Pattern nel Frontend (Angular)

  1. 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.
  2. Module Lazy Loading: Ogni modulo funzionale dell'ERP (es. Magazzino, Contabilità) deve avere il proprio routing.module ed 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.