Gestione di servizi multifunzione in rapida crescita

3

Il mio team ha sviluppato un'applicazione web business da oltre un anno. È iniziato abbastanza piccolo, ma ora sta crescendo sempre più grande. Penso che sia tempo di refactoring.

Guardando il codice, vedo la seguente situazione:

IUserService

  • addUser
  • deleteUser
  • UpdateUser
  • addMember
  • deleteMember
  • updateMember
  • registerMember
  • deactivateMember
    ....
  • getExpiringMember
  • nominateMember

In generale, ci sono circa 50 funzioni per più di 2500 linee di business logic. Una volta ho letto "Clean code", afferma che non ci dovrebbero essere più di 200 linee per una classe normale. Il nostro codice viola seriamente questo requisito e sto iniziando a sentire le difficoltà della gestione del codice.

La soluzione semplice potrebbe essere quella di suddividere questo servizio in molti altri servizi, ma non è fattibile / ragionevole:

  1. Questa classe di servizio funge da punto API per il client mobile, in modo che ogni modifica sull'interfaccia (anche la ridenominazione) richieda modifiche anche per il client. Non voglio passare il tempo prezioso della nostra squadra se non per una buona ragione.

  2. Ho già diviso una parte di questo servizio in un'altra classe, ma anche quella classe (RegistrationService) è cresciuta abbastanza velocemente e ha raggiunto 500 righe di codice di recente.

  3. Di recente, sempre più richieste di business logic, e questi servizi cresceranno ancora di più.

Ho paura che a un certo punto perderemo le tracce se un membro del team che gestisce un servizio specificato è andato in pensione.

C'è un modo per rendere questo servizio più gestibile? Qualche modello di disegno, tecnica di refactoring che posso applicare? Non sono ancora abbastanza esperto in questo campo ... eventuali suggerimenti o indicazioni sono ben accetti.

    
posta Hoàng Long 20.07.2012 - 09:58
fonte

2 risposte

3

Non sono un esperto di Spring ma dall'esperienza di progettazione / architettura generale mi sembra che troppi metodi per una singola API / servizio. È una specie di odore di design vedere questi molti metodi in un'unica interfaccia.

Dovresti provare a suddividerlo in aree di funzionalità logicamente distinte, ciascuna con un'interfaccia separata. Quindi il codice per implementare ogni area distinta dovrebbe diventare gestibile.

Se hai un codice client difficile da modificare, allora è meglio mantenere la vecchia versione del servizio - basta trasformarlo in una facciata leggera che chiama nelle nuove versioni refactored. I tuoi clienti non dovranno cambiare nulla se non lo desiderano (anche se dovresti chiarire che dovranno passare alle nuove interfacce se vogliono accedere a qualsiasi funzionalità futura).

Dai giusti metodi elencati nella domanda precedente potresti avere almeno quattro domini separati:

  • Gestione utenti
  • Gestione dei membri
  • Registrazioni (registrati, ecc.)
  • Nomination (nominateMember ecc.)
  • ecc.
risposta data 20.07.2012 - 10:26
fonte
2

Sembra che tu non possa dividere l'interfaccia di servizio in classi / servizi diversi, per mantenere la retrocompatibilità.

Ciò che dovrebbe fare, però, è dividere la funzionalità in classi in base a SRP, e quindi (best-case) avere interfacce per tali classi come dipendenze nel costruttore della classe di servizio o (peggio -case) instatialo tutti nel costruttore.

Ogni metodo nella classe di servizio diventa una singola linea di bontà, e il resto della tua applicazione può essere saggiamente pensato senza modificare l'API pubblica.

Esempio:

public class Service : IUserService
{
    private IUserRepository userRepo;
    private IMemberStuff memStuff;

    public Service(IUserRepository userRepo, IMemberStuff memStuff)
    {
       this.userRepo = userRepo;
       this.memStuff = memStuff;
    }

    public void addUser(...)
    {
        userRepo.addUser(...);
    }

    public void deleteUser(...)
    {
    }

    public void updateUser(...)
    {
    }

    public void addMember(...)
    {
    }

    public void deleteMember(...)
    {
    }

    public void updateMember(...)
    {
    }

    public void registerMember(...)
    {
    }

    public void deactivateMember(...)
    {
    }

    public Member getExpiringMember(...)
    {
    }

    public void nominateMember(...)
    {
    }
}
    
risposta data 20.07.2012 - 12:07
fonte

Leggi altre domande sui tag