Classes de serviço sem estado e decomposição de método

5

Eu gosto de implementar classes de serviço como sem estado. No entanto, também gosto de decompor minha lógica em métodos ou funções mais simples. Em alguns cenários parece que os dois são um pouco contra o outro. Considere os dois exemplos a seguir.

Eu tenho um objeto de entidade chamado House , implementado algo assim.

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. Implementação com estado

Prós: código mais limpo, nenhum parâmetro infernal

Contras: um serviço por um House , dificulta a injeção de dependência devido ao parâmetro construtor

public class HouseCleaner {

  private readonly House _house;

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

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

2. Implementação sem estado

Prós: a instância do serviço pode ser compartilhada, facilita a injeção de dependência

Contras: precisa passar muitos parâmetros para todos os métodos e funções simples para compartilhar o estado atual

public class HouseCleaner {

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

Qual você se sente mais apropriado considerando que este é um exemplo simplificado? Na realidade, pode haver várias dependências de serviço e outros parâmetros também.

    
por Zoltán Tamási 08.02.2016 / 14:44
fonte

3 respostas

2

Existem argumentos para ambos. A escolha como se diz "depende". A primeira abordagem pode ser dimensionada, porque você pode criar muitas instâncias de serviço (por exemplo, serviço multithread), mas o serviço deve ser leve. A segunda abordagem, por outro lado, é mais adequada para serviços "gordos" que demoram a instanciar. É melhor compartilhá-los. Quanto aos contras que você mencionou, ele pode ser aplicado a ambas as variantes. Mas isso pode ser superado usando aggreagates. Como Mark Seeman afirma em seu livro "Dependency injection in .NET" - você deve encontrar ou criar uma classe mais agregada que combine as classes desejadas, fornecendo um significado mais amplo.

    
por 12.02.2016 / 21:56
fonte
2

Não vejo isso como uma questão de vantagens e desvantagens técnicas. Depende do ciclo de vida de um HouseCleaner , o que é semanticamente e como se relaciona semanticamente a um House .

Suponha que você esteja lidando com Car e Wheel . Isso não faria sentido em reinjetar Car em Wheel uma na outra toda vez que o Car precisasse se mover. O Car simplesmente tem quatro Wheel objetos, e cada um desses Wheel objetos é anexado a esse único Car até que seja realocado de outra forma. Conceitualmente, semanticamente, é um relacionamento "permanente" e duradouro.

Compare isso com HoneyBee e Flower . A interação entre essas duas coisas é de curta duração ou transitória: escopo para interações simples.

Até agora, a injeção de dependência: não acredito que seja "mais difícil" de qualquer forma. Você pode injetar a dependência em ambos casos. Eles diferem principalmente em quando e quantas vezes você precisa injetar essa dependência.

Se o seu modelo está limpo e você chegou ao ponto de escrupulizar sobre se está tudo bem em manter o "estado" no lado do serviço; você basicamente precisa pesar o custo de carregar o estado da memória ou de um banco de dados com o custo de enviá-lo pelo fio (um fio muito mais longo e congestionado do que entre o serviço e o banco de dados) - e então remontá-lo e < em> validando .

    
por 12.02.2016 / 22:30
fonte
0

Através da pergunta e das respostas, vejo tudo ao redor do bullseye - The Visitor Pattern.

DoFactory, com um exemplo de C #, diz:

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 diz:

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.

Eu geralmente gosto do 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
    
por 29.05.2017 / 00:08
fonte

Tags