Come posso promuovere l'uso del modello Builder nella mia squadra?


22

La nostra base di codici è vecchi e nuovi programmatori, come me, imparano rapidamente a farlo nel modo in cui è fatto per motivi di uniformità. Pensando che dobbiamo iniziare da qualche parte, mi sono preso la responsabilità di refactoring di una classe di titolari di dati in quanto tale:

  • Rimossi i metodi setter e resi tutti i campi final(prendo " finalè buono" assiomaticamente). I setter sono stati utilizzati solo nel costruttore, a quanto pare, quindi questo non ha avuto effetti collaterali.
  • Introdotta una classe Builder

La classe Builder era necessaria perché il costruttore (che è ciò che ha richiesto il refactoring in primo luogo) si estende su circa 3 righe di codice. Ha molti parametri.

Per fortuna, un mio compagno di squadra stava lavorando su un altro modulo e aveva bisogno dei setter, perché i valori richiesti erano disponibili in diversi punti del flusso. Quindi il codice era simile al seguente:

public void foo(Bar bar){
    //do stuff
    bar.setA(stuff);
    //do more stuff
    bar.setB(moreStuff);
}

Ho sostenuto che avrebbe dovuto usare invece il builder, perché sbarazzarsi dei setter permette ai campi di rimanere immutabili (mi hanno già sentito parlare dell'immutabilità), e anche perché i costruttori permettono alla creazione di oggetti di essere transazionale. Ho delineato il seguente pseudocodice:

public void foo(Bar bar){
    try{
        bar.setA(a);
        //enter exception-throwing stuff
        bar.setB(b);
    }catch(){}
}

Se quell'eccezione si attiva, baravrà dati corrotti, che sarebbero stati evitati con un builder:

public Bar foo(){
        Builder builder=new Builder();
    try{
        builder.setA(a);
        //dangerous stuff;
        builder.setB(b);
        //more dangerous stuff
        builder.setC(c);
        return builder.build();
    }catch(){}
    return null;
}

I miei compagni di squadra hanno ribattuto che l'eccezione in questione non si attiverà mai, il che è abbastanza giusto per quella particolare area di codice, ma credo che manchi la foresta per l'albero.

Il compromesso consisteva nel ritornare alla vecchia soluzione, vale a dire usare un costruttore senza parametri e impostare tutto con setter come necessario. La logica era che questa soluzione segue il principio KISS, che il mio viola.

Sono nuovo di questa azienda (meno di 6 mesi) e sono pienamente consapevole di aver perso questa. Le domande che ho sono:

  • C'è un altro argomento per usare Builders invece del "vecchio modo"?
  • Ne vale davvero la pena il cambiamento che propongo?

ma veramente,

  • Hai qualche suggerimento per presentare meglio tali argomenti quando si sostiene di provare qualcosa di nuovo?

6
Il costruttore dovrà impostare i valori in qualche modo. Quindi non risolve il problema di base.
Amy Blankenship,

3
Qual è il motivo per cui le cose (più / pericolose / che generano eccezioni) non possono essere spostate prima della chiamata setA?
yatima2975,

2
Solo 3 righe di parametri del costruttore? Non è poi così male.
pjc50,

7
In qualsiasi progettazione software, ci sono sempre compromessi tra complessità e disaccoppiamento. Anche se penso di essere d'accordo con te personalmente sul fatto che il costruttore sia una buona soluzione qui, il tuo collega ha ragione a esitare per i motivi del KISS. Mantengo un software incredibilmente complicato, e parte del motivo è perché ogni nuova assunzione diventa canaglia e dice "Questo è stupido, farò questa nuova cosa a modo mio", quindi abbiamo 5 framework per la pianificazione processi in background e 8 metodi per l'interrogazione di un database. Tutto va bene con moderazione e non esiste una risposta chiara e chiara in casi come questo.
Brandon,

3
KISS è un concetto sfocato, gli oggetti modificabili sono fonte di complessità enormemente sottovalutata dagli sviluppatori, rendono il multi-threading, il debug e la gestione delle eccezioni molto più difficili di quelli immutabili. O l'oggetto è valido o viene creata un'eccezione nella costruzione (quale posto migliore per catturare quell'eccezione?).
Alessandro Teruzzi,

Risposte:


46

Pensando che dobbiamo iniziare da qualche parte, mi sono preso la responsabilità di riformattare una classe di titolari di dati

È qui che è andato storto: hai apportato una grande modifica architettonica alla base di codice in modo che diventasse molto diverso da quello che ci si aspettava. Hai sorpreso i tuoi colleghi. La sorpresa è buona solo se coinvolge una festa, il principio della minima sorpresa è d'oro (anche se coinvolge feste, saprei indossare mutande pulite!)

Ora, se pensavi che questo cambiamento fosse utile, sarebbe stato molto meglio abbozzare lo pseudocodice che mostrava il cambiamento e presentarlo ai tuoi colleghi (o almeno a chiunque abbia il ruolo più vicino all'architetto) e vedere cosa pensavano prima di fare qualsiasi cosa. Così com'è, sei diventato un ladro, pensavi che l'intera base di codice fosse tua con cui giocare come pensavi opportuno. Un giocatore della squadra, non un giocatore della squadra!

Potrei essere un po 'duro con te, ma sono stato nel posto opposto: controlla un po' di codice e pensa "WTF è successo qui ?!", solo per trovare il nuovo ragazzo (è quasi sempre il nuovo ragazzo) ha deciso di cambiare un carico di cose basato su ciò che pensa che il "modo giusto" dovrebbe essere. Vite anche con la storia di SCM, che è un altro grosso problema.


7
"La sorpresa è buona solo se coinvolge una festa" , non è vero per tutti !! Smetterei di parlare con qualsiasi cosiddetto amico che mi ha sorpreso qualsiasi cosa , specialmente una festa . Con le persone . Ugh.
Darkhogg,

3
Quindi, se ogni modello di refactoring e design o ogni decisione come "Uso qui l'accessorio e il mutatore o il modello del costruttore?" deve essere approvato da un team, come si sentiranno mai gli sviluppatori autorizzati a fare la cosa giusta? Come apporterai cambiamenti lungimiranti se tutto deve essere progettato da un comitato. Sono stato nei panni dell'OP prima in cui sono bloccato a dover mantenere un codice insensato (come il nuovo ragazzo) che tutti gli altri avevano paura di cambiare perché è coerente . La coerenza è buona e totale, ma non a spese del miglioramento.
Brandon,

11
@Brandon no, ma ogni cambiamento di vasta portata che li influenzerà dovrebbe. Se devi correggere un bug, è solo un altro pezzetto di codice - non è un grosso problema. Se prendi una decisione che riguarda tutti gli altri, allora è almeno educato dire loro quello che stai facendo. È possibile ottenere un accordo dal team per modificare il codice insensato, quindi le modifiche diventano la nuova coerenza. Devi solo parlare con i tuoi colleghi. Non c'è niente di male nel dire "Ho intenzione di cambiare il modello di accessorio scadente che tutti odiamo" e sentire i tuoi colleghi rispondere "sì, è ora che qualcuno se ne
occupi

13
@Brandon c'è un detto: "La strada per l'inferno è lastricata di buone intenzioni". La coerenza non è solo buona , è necessaria ! Immagina di provare a gestire un team di sviluppatori che gestiscono collettivamente 20 applicazioni, ognuna delle quali è scritta in uno stile e / o architettura diversi perché le preferenze, la tecnologia attuale, le tendenze, ecc. Hanno dettato ciò che era meglio in quel momento. Far concordare alla squadra che qualcosa dovrebbe cambiare può essere la differenza tra l'accettazione del nuovo ragazzo perché ha risolto un problema di vecchia data e il licenziamento per essere diventato un cavaliere con ciò che pensavi fosse meglio.
DrewJordan

3
@Brandon - Se hai intenzione di diventare un ladro e sistemare qualcosa "che tutti concordano sull'errore", allora avresti probabilmente più successo scegliendo qualcosa che "tutti concordano sull'errore" piuttosto che scegliere qualcosa che nella migliore delle ipotesi ha campi diversi sul argomento; come l'immutabilità. Un buon design / architettura rende l'immutabilità alto costo per praticamente nessuna ricompensa. Quindi, a meno che la tua squadra non abbia avuto problemi perché stanno usando setter, allora non stavi risolvendo affatto un problema. OTOH, se questa è stata una fonte di bug frequenti, allora sembra che le conseguenze giustifichino una decisione del team.
Dunk

21

Per fortuna, un mio compagno di squadra stava lavorando su un altro modulo e aveva bisogno dei setter, perché i valori richiesti erano disponibili in diversi punti del flusso.

Come descritto, non vedo ciò che rende il codice richiesto setter. Probabilmente non conosco abbastanza il caso d'uso, ma perché non aspettare che tutti i parametri siano noti prima di creare un'istanza dell'oggetto?

In alternativa, se la situazione richiede setter: offri un modo per bloccare il tuo codice a quei setter che generano un errore di asserzione (noto anche come errore del programmatore) se provi a modificare i campi dopo che l'oggetto è pronto.

Penso che rimuovere i setter e usare final sia il modo "corretto" di farlo, oltre a far rispettare l'immutabilità, ma è davvero quello con cui dovresti passare il tempo?

Suggerimenti generali

Vecchio = cattivo, nuovo = buono, a modo mio, a modo tuo ... questo tipo di discussione non è costruttiva.

Attualmente, il modo in cui viene utilizzato l'oggetto segue alcune regole implicite. Questo fa parte delle specifiche non scritte del tuo codice e il tuo team potrebbe pensare che non vi siano molti rischi per l'uso improprio di altre parti del codice. Quello che vuoi fare qui è rendere la regola più esplicita con un Builder e controlli in fase di compilazione.

In qualche modo il refactoring del codice è legato alla teoria Broken Window : ritieni giusto risolvere qualsiasi problema quando lo vedi (o prendi nota per un incontro di "miglioramento della qualità" successivo) in modo che il codice sembri sempre piacevole con cui lavorare, è sicuro e pulito. Tu e il tuo team non avete la stessa idea di ciò che è "abbastanza buono", però. Quello che vedi come un'opportunità per contribuire e migliorare il codice, in buona fede, è probabilmente visto in modo diverso dal team esistente.

A proposito, la tua squadra non dovrebbe presumibilmente soffrire di inerzia, cattive abitudini, mancanza di istruzione, ... il peggio che puoi fare è proiettare l'immagine di un conoscente che è lì per mostrarli come codificare. Ad esempio, l'immutabilità non è una novità , probabilmente i tuoi colleghi l'hanno letto, ma solo perché questo argomento sta diventando popolare nei blog non è sufficiente per convincerli a passare il tempo a cambiare il loro codice.

Dopotutto, ci sono infiniti modi per migliorare una base di codice esistente, ma costa tempo e denaro. Potrei guardare il tuo codice, chiamarlo "vecchio" e trovare cose di cui parlare. Ad esempio: nessuna specifica formale, asserzioni insufficienti, forse non abbastanza commenti o test, copertura del codice insufficiente, algoritmo non ottimale, uso eccessivo della memoria, non utilizzo del "migliore" modello di progettazione possibile in ciascun caso, ecc . Fino alla nausea . Ma per la maggior parte dei punti che vorrei sollevare, potresti pensare: va bene, il mio codice funziona, non c'è bisogno di dedicare più tempo ad esso.

Forse la tua squadra pensa che ciò che suggerisci sia passato al punto di rendimenti decrescenti. Anche se avessi trovato un'istanza reale di un bug a causa del tipo di esempio che mostri (con l'eccezione) probabilmente lo risolverebbero solo una volta e non vorranno refactificare il codice.

Quindi la domanda è su come spendere il tuo tempo ed energia, dato che sono limitati ? Ci sono continue modifiche apportate al software, ma generalmente la tua idea inizia con un punteggio negativo fino a quando non puoi fornire buoni argomenti ad esso. Anche se hai ragione sul vantaggio, non è un argomento sufficiente da solo, perché finirà nel cestino " Bello avere, un giorno ... ".

Quando presenti le tue argomentazioni, devi fare dei controlli di "sanità mentale": stai cercando di vendere l'idea o te stesso? E se qualcun altro lo avesse presentato alla squadra? Troveresti qualche difetto nel loro ragionamento? Stai cercando di applicare alcune best practice generali o hai preso in considerazione le specifiche del tuo codice?

Quindi, assicurati di non apparire come se stessi cercando di correggere gli "errori" passati della tua squadra. Aiuta a dimostrare che non sei la tua idea ma puoi ricevere un feedback ragionevolmente. Più lo fai, più i tuoi suggerimenti avranno l'opportunità di essere seguiti.


Hai assolutamente ragione. Una piccola obiezione: non è il "vecchio modo" contro "il mio nuovo, super fantastico nuovo modo". Sono pienamente consapevole del fatto che potrei parlare senza senso. Il mio problema è che continuando a utilizzare le pratiche software che tutti nella società trovano orribili, potrei ristagnare come sviluppatore. Quindi cerco di introdurre qualche cambiamento, anche se mi sbaglio. (L'attività è stata attivata da una richiesta di refactoring di una classe correlata)
rath

@rath Non ci sono nuove basi di codice in fase di sviluppo?
biziclop,

@biziclop Ci sono nuovi moduli che vengono inseriti nella vecchia base di codice. Ne ho lavorato uno di recente. Giorni felici.
rath

5
@rath Forse hai bisogno di un progetto personale su cui puoi lavorare nei tuoi tempi in cui puoi avanzare nel tuo sviluppo? Non sono neanche convinto dal tuo argomento "Builder"; i getter / setter sembrano essere una soluzione perfettamente OK in base alle informazioni fornite. Ricorda che sei responsabile nei confronti del tuo datore di lavoro e della tua squadra; la tua priorità è assicurarti che qualsiasi lavoro che fai sia di beneficio a coloro a cui sei responsabile.
Ben Cottrell,

@rath Bene, anche se non sei in un codice "vecchio / nuovo", ciò che conta è come viene percepito dalla parte ricevente, specialmente se hanno più potere decisionale di te. Sembra che tu voglia introdurre un cambiamento per il tuo interesse e non per il prodotto che sviluppi. Se tutti in azienda trovano la pratica orribile, alla fine cambierà, ma questo non sembra essere una priorità.
coredump,

17

Come posso promuovere l'uso del modello Builder nella mia squadra?

Non

Se il tuo costruttore ha 3 linee di parametri, è troppo grande e troppo complesso. Nessun modello di progettazione lo risolverà.

Se hai una classe i cui dati sono disponibili in momenti diversi, dovrebbero essere due oggetti diversi, oppure il tuo consumatore dovrebbe aggregare i componenti e quindi costruire l'oggetto. Non hanno bisogno di un costruttore per farlo.


È un grande detentore di dati di Stringse primitivi. Non c'è logica da nessuna parte, nemmeno per verificare la presenza di nullecc. Quindi sono solo dimensioni, non complessità in sé. Pensavo che fare qualcosa del genere builder.addA(a).addB(b); /*...*/ return builder.addC(c).build();sarebbe stato molto più facile per gli occhi.
rath

8
@rath: è un detentore di big data di stringhe e altri primitivi. => allora hai altri problemi, spero che a nessuno importi se il campo di posta elettronica accidentale viene assegnato con l'indirizzo postale del ragazzo ...
Matthieu M.

@MatthieuM. Un problema alla volta suppongo :)
rath

@rath - Sembra che incorporare un buon schema di verifica della validazione sarebbe stato molto più utile e più prontamente ricevuto che cercare di capire come sgangherare il modello del builder in codice già esistente. Da qualche altra parte hai detto che vuoi migliorare te stesso. Imparare come ottenere il massimo guadagno con il minimo sforzo e conseguenze è sicuramente un attributo che dovrebbe essere sviluppato.
Dunk

1
Ho moltissimi costruttori con molti più parametri di così. Necessario nei modelli IoC. Cattiva generalizzazione in questa risposta.
Djechlin,

16

Sembri più concentrato sull'avere ragione che sul lavorare bene con gli altri. Peggio ancora, riconosci che ciò che stai facendo è una lotta di potere e tuttavia non riesci a pensare a come è probabile che le cose sentano le persone la cui esperienza e autorità ti sfidano.

Invertire quello.

Concentrati sul lavorare con gli altri. Inquadra i tuoi pensieri come suggerimenti e idee. Chiedi a LORO di parlare attraverso le LORO idee prima di porre domande per farle riflettere sulle tue. Evita gli scontri diretti e sii esternamente disposto ad accettare che andare avanti nel fare le cose nel modo in cui il gruppo (per ora) è più produttivo di combattere una battaglia in salita per cambiare il gruppo. (Anche se riporta le cose.) Rendi il lavoro con te una gioia.

Fai questo in modo coerente e dovresti creare meno conflitti e trovare più idee che vengano adottate da altri. Tutti noi soffriamo dell'illusione che l'argomentazione logica perfetta stupirà gli altri e vincerà il giorno. E se non funziona in questo modo, pensiamo che dovrebbe .

Ma questo è in diretto conflitto con la realtà. La maggior parte degli argomenti viene persa prima che il primo punto logico fosse raggiunto. Anche tra persone presumibilmente logiche, la psicologia batte la ragione. Convincere le persone significa superare le barriere psicologiche per essere ascoltati correttamente e non avere una logica perfetta.


2
Frame your thoughts as suggestions and ideas. Get THEM to talk through THEIR ideas before asking questions to make them think about yours+1 per quello
rath

2
@rath Tieni presente che altre persone potrebbero non leggere dal tuo libro. È possibile che la persona con cui stai discutendo la consideri come un confronto, che potrebbe essere controproducente per i tuoi obiettivi.
Iker,

2
@rath: non c'è giusto o sbagliato. Solo compromessi. E il più delle volte i compromessi coinvolgono più del solo codice.
Marjan Venema,

1
@Dunk Tutto ciò che esiste sono compromessi. Li chiamiamo giusti o sbagliati quando i compromessi sono cristallini e ovviamente da una parte. Tuttavia, riconoscere quando le sfumature diventano ambigue è più facile se ci concentriamo sul fatto che siano compromessi sin dall'inizio.
btilly

2
Non esiste un'unica "buona pratica" di programmazione di cui sono a conoscenza, che non ha eccezioni laddove non sia la migliore. A volte è difficile trovare quelle eccezioni, ma esistono sempre.
btilly

11

C'è un altro argomento per usare Builders invece del "vecchio modo"?

"Quando hai un nuovo martello, tutto sembrerà un chiodo." - questo è quello che ho pensato quando ho letto la tua domanda.

Se fossi il tuo collega, ti chiederei "perché non inizializzare l'intero oggetto nel costruttore?" Questa è la sua funzionalità dopo tutto. Perché usare il modello builder (o qualsiasi altro disegno)?

Ne vale davvero la pena il cambiamento che propongo?

È difficile distinguerlo da quel piccolo frammento di codice. Forse lo è - tu e i tuoi colleghi dovete valutarlo.

Hai qualche suggerimento per presentare meglio tali argomenti quando si sostiene di provare qualcosa di nuovo?

Sì, scopri di più sull'argomento prima di discuterne. Armati di buoni argomenti e razionali prima di entrare nella discussione.


7

Sono stato nella situazione in cui sono stato reclutato per le mie capacità. Quando ho avuto modo di vedere il codice, beh ... era più che orribile. Quando poi cerca di ripulirlo, qualcuno che è stato più a lungo sopprime sempre le modifiche, perché non ne vede i benefici. Sembra qualcosa che stai descrivendo. Si è concluso con me che ho lasciato quella posizione e ora posso evolvere molto meglio in un'azienda che ha una pratica migliore.

Non penso che dovresti recitare insieme agli altri nel team perché sono stati lì più a lungo. Se vedi i membri del tuo team che usano cattive pratiche nei progetti in cui lavori, è una responsabilità che devi sottolineare, così come hai. In caso contrario, non sei una risorsa molto preziosa. Se indichi le cose più e più volte, ma nessuno ti sta ascoltando, chiedi alla direzione un lavoro sostitutivo o cambia. È molto importante che non ti permetta di adattarti alle cattive pratiche lì.

Alla domanda reale

Perché usare oggetti immutabili? Perché sai con cosa hai a che fare.

Supponi di avere una connessione db passata che ti consente di cambiare l'host attraverso un setter, quindi non sai di quale connessione si tratti. Essere immutabili, allora lo sai.

Supponiamo tuttavia che tu abbia una struttura di dati che può essere recuperata dalla persistenza e quindi ripresentata con nuovi dati, quindi ha senso che questa struttura non sia immutabile. È la stessa entità, ma i valori possono cambiare. Utilizzare invece oggetti valore immutabili come argomenti.

Ciò su cui stai focalizzando la domanda è tuttavia un modello di costruzione per sbarazzarsi delle dipendenze nel costruttore. Dico un grosso grasso NO a questo. L'istanza è ovviamente già complessa. Non cercare di nasconderlo, risolvilo!

Tl; dr

La rimozione dei setter può essere corretta, a seconda della classe. Il modello del costruttore non sta risolvendo il problema, ma semplicemente nascondendolo. (La sporcizia sotto il tappeto esiste ancora anche se non riesci a vederlo)


Non conosco i dettagli della tua situazione, ma se sei arrivato e hai cercato di cambiare tutto senza prima acquisire la fiducia delle persone con le tue abilità o non prendere il tempo di imparare "perché" fanno le cose come fanno, allora sei stato trattato esattamente come verrai trattato presso qualsiasi azienda, anche se davvero brava. In realtà, specialmente a quelli veramente buoni. Una volta che le persone hanno fiducia nelle abilità di qualcuno, allora è semplicemente una questione convincente per i tuoi suggerimenti. Se non riesci a presentare un caso convincente, allora c'è una buona probabilità che il tuo suggerimento non sia poi così buono.
Dunk,

1
idk cosa rispondere alle tue assunzioni @Dunk Non stavo cercando di cambiare tutto, ho provato a ripulirlo. E non erano le persone che sapevano cosa stavano facendo, hanno creato con orgoglio classi e funzioni in cui centinaia di righe di codice, con idk quanti stati, globali e così via .. il livello era più vicino a kinder garden imo. Quindi sostengo la mia affermazione. Non arrenderti mai quando noti che sei in una posizione in cui dovrai adottare una cattiva pratica per adattarti.
supereroe

@Dunk Prova a cambiare il modo in cui il codice persone come membro del team non è quello che faccio. Ma dico loro dall'inizio; "Non lavorerò in questo progetto senza riscriverlo completamente" , se il codice è un cestino che lo è. Se questo non è appropriato, beh ... allora è reciproco. Non si tratta solo di un conforto, si tratta del fatto che devo essere in grado di assumermi la responsabilità di ciò che produco. Non posso farlo se il codice circostante nel progetto è un casino completo.
supereroe

Non devi lavorare "per sempre" con il codice che è spazzatura o seguire cattive pratiche semplicemente perché è così che viene fatto. Tuttavia, se vuoi avere successo nel cambiare le cose, allora è meglio dimostrare prima la tua credibilità come minimo. Quasi tutti gli sviluppatori pensano che il codice che ereditano sia spazzatura. Se ogni azienda ha appena concordato con il nuovo ragazzo ogni volta senza nemmeno conoscere il loro vero livello di abilità, la spazzatura si trasformerà in una discarica. Inoltre, dovresti prenderti il ​​tempo per capire perché le cose sono fatte così come sono. A volte il modo "sbagliato" è il modo "giusto" per una situazione specifica.
Dunk

@Dunk Vedo che hai un'opinione diversa rispetto a me in questa materia. I tuoi sembrano essere più popolari, se leggi dalle altre risposte. Non sono d'accordo, perché ho scritto questa risposta in opposizione. Quello che hai affermato non mi ha cambiato idea.
supereroe

2

Mentre tutte le altre risposte sono molto utili (più utili delle mie), esiste una proprietà dei costruttori che non hai ancora menzionato: trasformando la creazione di un oggetto in un processo, puoi applicare vincoli logici complessi.

Ad esempio, è possibile imporre che determinati campi siano impostati insieme o in un ordine specifico. È anche possibile restituire un'implementazione diversa dell'oggetto target in base a tali decisioni.

// business objects

interface CharRange {
   public char getCharacter();
   public int getFrom();
   public int getTo();
}

class MultiCharRange implements CharRange {
   final char ch;
   final int from;
   final int to;

   public char getCharacter() { return ch; }
   public int getFrom() { return from; }
   public int getTo() { return to; }
}

class SingleCharRange implements CharRange {
   final char ch;
   final int position;

   public char getCharacter() { return ch; }
   public int getFrom() { return position; }
   public int getTo() { return position; }
}

// builders

class Builder1 {
   public Builder2 character(char ch) {
      return new Builder2(ch);
   }
}

class Builder2 {
   final char ch;
   int from;
   int to;

   public Builder2 range(int from, int to) {
      if (from > to) throw new IllegalArgumentException("from > to");
      this.from = from;
      this.to = to;
      return this;
   }

   public Builder2 zeroStartRange(int to) {
      this.from = 0;
      this.to = to;
      return this;
   }

   public CharRange build() {
      if (from == to)
         return new SingleCharRange(ch,from);
      else 
         return new MultiCharRange(ch,from,to);
   }
}

Questo è un bell'esempio che non ha molto senso ma dimostra tutte e tre le proprietà: il personaggio è sempre impostato per primo, i limiti di intervallo sono sempre impostati e convalidati insieme e scegli l'implementazione al momento della creazione.

È facile vedere come questo possa portare a un codice utente più leggibile e affidabile, ma come puoi anche vedere, c'è un aspetto negativo: un sacco di codice builder (e ho anche lasciato fuori i costruttori per abbreviare gli snippet). Quindi si tenta di calcolare il compromesso, ponendo domande come:

  • Istanziamo l'oggetto solo da uno o due punti? È probabile che questo cambi?
  • Forse dovremmo applicare questi vincoli rifattorizzando l'oggetto originale in una composizione di oggetti più piccoli?
  • Finiremmo per passare il builder da un metodo all'altro?
  • Potremmo semplicemente usare un metodo statico di fabbrica invece?
  • Questa parte di un'API esterna, che deve essere il più semplice e sicura possibile?
  • Approssimativamente, quanti dei nostri attuali arretrati di bug avrebbero potuto essere evitati se avessimo costruttori?
  • Quanta documentazione aggiuntiva vorremmo risparmiare?

I tuoi colleghi hanno semplicemente deciso che il compromesso non sarebbe vantaggioso. Dovresti discutere le ragioni apertamente e onestamente, preferibilmente senza ricorrere a principi astratti, ma concentrandoti sulle implicazioni pratiche di questa soluzione o quella.


1
trasformando la creazione di un oggetto in un processo, è possibile applicare vincoli logici complessi. BAM. E tutto ciò che ciò implica sulla complessità quando è organizzato in passaggi più piccoli, discreti e più semplici .
radarbob

2

Sembra che questa classe sia in realtà più di una classe, messa insieme nella stessa definizione di file / classe. Se si tratta di un DTO, dovrebbe essere possibile istanziarlo in una volta sola e renderlo immutabile. Se non usi tutti i suoi campi / proprietà in nessuna transazione, allora quasi sicuramente infrange il principio della responsabilità singola. Potrebbe essere che suddividerlo in classi DTO più piccole, più coerenti e immutabili potrebbe aiutare. Prendi in considerazione la possibilità di leggere Clean Code se non l'hai già fatto, così sei in grado di articolare meglio i problemi e i vantaggi di apportare una modifica.

Non credo che tu possa progettare il codice a questo livello dal comitato, a meno che tu non stia letteralmente programmando mob (non sembra che tu faccia parte di quel tipo di squadra), quindi penso che sia giusto fare un cambiamento in base al tuo miglior giudizio, e poi prenderlo sul mento se si scopre che lo hai giudicato sbagliato.

Tuttavia, fintanto che sei in grado di articolare le potenziali problematiche con il codice così com'è, puoi comunque discutere che sia necessaria una soluzione , anche se la tua non è quella accettata. Le persone sono quindi libere di offrire alternative.

" Opinioni forti, debolmente mantenute " è un buon principio: vai avanti con fiducia in base a ciò che conosci, ma se trovi alcune nuove informazioni che contrastano, sii modesto e dimettiti e inserisci una discussione su quale dovrebbe essere la soluzione corretta essere. L'unica risposta sbagliata è lasciarla peggiorare.


Non è sicuramente progettato dal comitato, il che è parte del motivo per cui il codice puzza così tanto. Troppo di buono suppongo. Si tratta di un DTO ma non voglio romperlo in pezzi; se la base di codice è errata, il DB è molto, molto peggio. +1 (principalmente) per l'ultimo paragrafo.
rath
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.