Clean Code e il principio di Least Astonishment

2

Nella documentazione di Java , si afferma:

Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.

Da Pulisci codice (pagina 25):

When constructors are overloaded, use static factory methods with names that describe the arguments

For example:

Complex fulcrumpoint = Complex.FromRealNumber(23.0);

is generally better than

Complex fulcrumPoint = new Complex(23.0);

Ma secondo i commenti a questa risposta , quando si tratta di questo codice:

private Weapon(String name, int damage)
{
    this.name = name;
    this.damage = damage;
}

public void attack(Enemy enemy){ // code to cause damage to enemy }

public static Weapon Sword(String name, damage){
    return new Weapon(name, damage);
}

public static Weapon Sniper(String name, damage){
    return new Weapon(name, damage);
}

It'll compile and execute, but it violates the Principle of least astonishment.

L'autore di Clean Code ha violato il Principio di Least Astonishment per scrivere quello che è considerato codice pulito?

    
posta Christophe 02.03.2018 - 18:34
fonte

4 risposte

4

Anche dal link:

@S.R.: no, it's not fine. It'll compile and execute, but it violates the Principle of least astonishment. If you want to create an object, you should normally use new.

Questo sembra un consiglio molto obsoleto. Al giorno d'oggi è molto comune usare metodi di fabbrica o un'iniezione di dipendenza per ottenere una nuova istanza di qualcosa. Detto questo, le fabbriche statiche sono fuori moda; dovresti iniettare un factory istanziato con un'interfaccia e impostare il contenitore IoC su una singola istanza.

    
risposta data 02.03.2018 - 19:05
fonte
4

No, non l'ha fatto.

Il punto del consiglio di evitare new SpecificType() è che non c'è modo di usare un costruttore senza codificare la classe esatta che si desidera utilizzare. Poiché la codifica delle interfacce piuttosto che delle implementazioni è un'ottima idea, abbinarsi a una particolare classe concreta di solito è una cattiva idea. Questo è uno dei motivi per cui le fabbriche e i metodi di fabbrica sono così popolari: solo la fabbrica deve cambiare quando inventi un nuovo ImprovedSpecificClass , non il codice cliente. (Ce ne sono altri, ad esempio la possibilità di avere nomi più informativi per i metodi di creazione rispetto a SpecificClass() , ma considero questo il vantaggio principale.)

L'esempio, tuttavia, mostra il codice all'interno della classe Weapon che chiama un costruttore Weapon . Non c'è modo di disaccoppiare Weapon da se stesso, quindi non c'è motivo di evitare new . Fare ciò significherebbe che qualcuno ha capito la lettera ma non lo spirito dei metodi di fabbrica.

    
risposta data 02.03.2018 - 19:21
fonte
0

La citazione che hai fornito contiene una qualifica importante:

When constructors are overloaded [...]

Quando hai solo un modo ovvio per istanziare un oggetto, un semplice costruttore andrà benissimo. Ma se hai un certo numero di modi diversi per creare l'oggetto, un costruttore con nome può spesso comunicare l'intento meglio che fare in modo che l'utente cerchi il sovraccarico del costruttore corrispondente.

Questo non è uno schema insolito. Come è stato affermato, l'esempio di Weapon è un po 'strano, perché entrambi i metodi di fabbrica fanno esattamente la stessa cosa.

    
risposta data 03.03.2018 - 00:36
fonte
0

Vorrei rispondere a una parte specifica del codice dalla tua domanda:

public static Weapon Sword(String name, damage){
    return new Weapon(name, damage);
}

public static Weapon Sniper(String name, damage){
    return new Weapon(name, damage);
}

Questi due metodi di fabbrica violano il Principio di Least Astonishment in alcuni aspetti seri:

  • Non seguono le convenzioni di denominazione Java (i nomi dei metodi dovrebbero iniziare con lettere minuscole).
  • Quello che fanno, non ha niente a che fare con i loro nomi: entrambi producono Waepon non specifici, e non c'è nulla riguardo a Swords o Snipers in essi.
  • Sono due metodi che fanno esattamente lo stesso lavoro.
risposta data 03.03.2018 - 20:19
fonte

Leggi altre domande sui tag