Perché utilizzare un attributo interno per filtrare gli oggetti considerati OK, ma quando uso una mappa per filtrare in base agli attributi, è considerato un odore di codice?

1

Molto tempo fa ho chiesto sull'utilizzo di un enum per usare essenzialmente come una versione povera di instanceof per prendere decisioni su un oggetto.

Come indicato in questa risposta:

When your weapon types enum just mirrors the class hierarchy, then this is a blatant violation of the DRY principle - you encode the same information, the type of a weapon redundantly in two places - one place is the class name itself, one place the enum. That's definitely not just a code smell, that is bad code.

Ho quindi mi sono chiesto a proposito di avere un List o un Map che conteneva una raccolta di attributi che l'oggetto poteva contenere e che utilizzava un metodo, vorrei chiedergli quali attributi conteneva e quindi procedere a lavorare con quell'oggetto.

Mettiamo da parte l'idea Collection per ora, perché voglio concentrarmi su un altro problema correlabile.

In Clean Code, P.19 il seguente frammento di codice è fornito come un buon esempio di metodi e variabili ben denominati.

public List<Cell> getFlaggedCells(){
    List<Cell> flaggedCells = new ArrayList<Cell>();
    for(Cell cell : gameboard){
         if(cell.isFlagged()){
              flaggedCells.add(cell);
         }
    }
    return flaggedCells;
}  

Da questo frammento di codice, sappiamo che un cell contiene un metodo che verifica se è stato contrassegnato. In altre parole, possiamo chiedere alla cella, sei contrassegnato?

Raccogliamo quindi un List di celle contrassegnate e torniamo al chiamante.

Nella mia seconda domanda, ho avuto il seguente frammento di codice:

public abstract class Weapon 
{
    private List<GameObjectAttributes> gOAttributes;

    // imagine a constructor :D.

    public final boolean containsAttribute(GameObjectAttributes attribute)
    {
        // determine if weapon contains a specific attribute. 
    }
}

Una classe Wizard potrebbe apparire come questa:

public Wizard extends Character {

    private List<Weapons> weapons;

    public boolean tryAdd(Weapon weapon){
       if !(weapon.containsAttribute(WeaponType.LongBlade)){
          return weapons.add(weapon);
       }
       return false;     
    }
}

Molto simile allo snippet Clean Code, sto chiedendo l'oggetto, conterrai un attributo specifico e, in caso contrario, aggiungilo alla raccolta weapons .

Come indicato in questo link , utilizzando una enum per mappare i comportamenti polimorfici è un odore di codice, e giustamente. Lo stesso avviso è dato nel mio secondo link in alto.

Domanda:

Perché l'esempio del codice pulito è considerato soddisfacente, utilizzando un attributo interno per filtrare gli oggetti, ma quando uso una mappa per filtrare in base agli attributi, è considerato odore di codice?

Sono non che verifica un attributo specifico e poi chiamo un metodo per eseguire un'azione, sto semplicemente filtrando, niente di più, niente di meno.

    
posta Robert Harvey 04.10.2018 - 16:16
fonte

1 risposta

2

Non vedo un problema con il tuo codice perché esiste una chiara distinzione tra un Arma e un Attributo Arma .

Il tuo WeaponType enum non sembra modellare direttamente la gerarchia delle classi di armi. WeaponType.LongBlade potrebbe essere un attributo di Kitana o Machete .

Ovviamente avresti un comportamento di gioco diverso in base al tipo di arma usata, e penso che tu abbia ragione nell'usare gli attributi delle armi per farlo.

Forse mi manca qualcosa, ma penso che quello che hai va bene.

    
risposta data 04.10.2018 - 20:22
fonte

Leggi altre domande sui tag