Classi di servizio stateless e scomposizione del metodo

5

Mi piace implementare classi di servizio come stateless. Tuttavia, mi piace anche scomporre la mia logica in più, semplici metodi o funzioni. In alcuni scenari sembra che i due siano un po 'l'uno contro l'altro. Considera i seguenti due esempi.

Ho un oggetto entità chiamato House , implementato qualcosa di simile.

public class House {
  public string Address { get; set; }
  public List<Room> Rooms { get; set; }

  ...

  public IEnumerable<Furniture> GetAllFurnitures() {
    return Rooms.SelectMany(e => e.Furnitures);
  }

  ...
}

1. Implementazione stateful

Pro: codice più pulito, nessun parametro infernale

Contro: un servizio per uno House , rende più difficile l'iniezione della dipendenza a causa del parametro costruttore

public class HouseCleaner {

  private readonly House _house;

  public HouseCleaner(House house) {
    _house = house;
  }

  public void Clean() {
    vacuumClean();
    cleanBathroom();
    cleanToilettes();
    cleanKitchen();
    wipeFloor();
  }
}

2. Implementazione senza stato

Vantaggi: l'istanza del servizio può essere condivisa, facilita l'immissione delle dipendenze

Contro: è necessario passare probabilmente molti parametri a tutti i metodi e le funzioni semplici per condividere lo stato corrente

public class HouseCleaner {

  public void Clean(House house) {
    vacuumClean(house);
    cleanBathroom(house);
    cleanToilettes(house);
    cleanKitchen(house);
    wipeFloor(house);
  }
}

Quale ti senti più appropriato considerando che questo è un esempio semplificato. In realtà potrebbero esserci diverse dipendenze del servizio e anche altri parametri.

    
posta Zoltán Tamási 08.02.2016 - 14:44
fonte

3 risposte

2

Ci sono argomenti per entrambi. La scelta come si dice "dipende". Il primo approccio può essere ridimensionato, poiché è possibile creare molte istanze di servizio (ad esempio il servizio multithread), ma il servizio deve essere leggero. D'altro canto, il secondo approccio è più adatto per servizi "grassi" che richiedono tempo per creare un'istanza. È meglio condividerli Per quanto riguarda gli svantaggi che hai menzionato, può essere applicato a entrambe le varianti. Ma può essere superato usando aggragates. Come afferma Mark Seeman nel suo libro "Dependency injection in .NET", dovresti trovare o creare una classe più aggregata che unisca le classi desiderate, fornendo un significato più ampio.

    
risposta data 12.02.2016 - 21:56
fonte
2

Non vedo questo come una questione di pro e contro tecnici. Dipende dal ciclo di vita di un HouseCleaner , di ciò che è semanticamente e di come esso semanticamente a House .

Supponi di avere a che fare con Car e Wheel . Non farebbe una lecchiosa sensazione di ri-iniettare Car in Wheel l'uno dentro l'altro ogni volta che Car ha bisogno di spostarsi. Il Car semplicemente ha quattro% oggettiWheel, e ciascuno di quegli oggetti Wheel è collegato a quel singolo Car fino a quando non viene spostato in altro modo. Concettualmente, semanticamente, è una relazione di lunga durata, "permanente".

Contrasto con HoneyBee e Flower . L'interazione tra queste due cose è di breve durata o transitoria: circoscritta a singole interazioni.

Per quanto riguarda l'iniezione della dipendenza: non credo che sia "più difficile" in entrambi i casi. Si arriva a iniettare la dipendenza in casi di entrambi . Differiscono principalmente in quando e con quale frequenza devi iniettare tale dipendenza.

Se il tuo modello è pulito e sei arrivato al punto di scrupolarsi sulla possibilità di mantenere lo "stato" sul lato del servizio; per lo più devi solo pesare il costo di caricare lo stato dalla memoria o da un database contro il costo di inviarlo via cavo (un cavo molto più lungo e congestionato di quanto ci sia tra il servizio e il database) - e quindi rimontarlo e < em> convalidare it.

    
risposta data 12.02.2016 - 22:30
fonte
0

Attraverso la domanda e le risposte vedo tutto ciò che colpisce intorno al bullseye - The Visitor Pattern.

DoFactory, con un esempio in C #, dice:

Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Wikipedia dice:

the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to extant object structures without modifying the structures. It is one way to follow the open/closed principle.

In essence, the visitor allows adding new virtual functions to a family of classes, without modifying the classes.

In genere mi piace SourceMaking.com

  • Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

  • The classic technique for recovering lost type information.

  • Do the right thing based on the type of two objects.
  • Double dispatch
    
risposta data 29.05.2017 - 00:08
fonte

Leggi altre domande sui tag