As classes de gerente podem ser um sinal de arquitetura ruim?

49

Ultimamente, comecei a pensar que ter muitas classes de gerente em seu design é uma coisa ruim. A ideia não amadureceu o suficiente para eu apresentar um argumento convincente, mas eis alguns pontos gerais:

  • Eu achei muito mais difícil para mim entender sistemas que dependem muito de "gerentes". Isso ocorre porque, além dos componentes reais do programa, você também precisa entender como e por que o gerente é usado.

  • Os gerentes, na maioria das vezes, parecem ser usados ​​para aliviar um problema com o design, como quando o programador não conseguia encontrar uma maneira de criar o programa Just Work TM e tinha que confiar nas classes de gerenciadores para fazer tudo funcionar corretamente.

Claro, os gerentes podem ser bons. Um exemplo óbvio é uma EventManagerdas minhas construções favoritas de todos os tempos. : P O que quero dizer é que os gerentes parecem ser usados ​​em excesso a maior parte do tempo e por nenhuma outra razão além de mascarar um problema com a arquitetura do programa.

As classes de gerente são realmente um sinal de arquitetura ruim?

Paulo
fonte
5
Eu acho que Of course, mangers can be good. An obvious example is an EventManagerexplica tudo bem ali. Um mau uso do conceito é uma arquitetura ruim, mas há casos de uso legítimos. O mesmo vale para quase tudo.
27
Parece mais provável que seja um sinal de nomeação sem imaginação.
Pd
9
EventManageré um nome horrível para uma classe. Aparentemente, faz algo com os eventos, mas o que ?
Christoffer Hammarström
5
um dos problemas aqui é uma limitação de idioma steve-yegge.blogspot.com/2006/03/… As classes de gerente geralmente são devidas a verbos de substantivo, funções livres são o que realmente é desejado
jk.
11
Os gerentes geralmente têm muito poder (responsabilidades) e podem ser difíceis de lidar - como em qualquer ambiente de escritório;) EventManager não significa nada. EventDispatcher descreve o que faz.
CodeART

Respostas:

31

As classes de gerente podem ser um sinal de uma arquitetura incorreta, por alguns motivos:

  • Identificadores sem sentido

    O nome FooManagernão diz nada sobre o que a classe realmente faz , exceto que de alguma forma envolve Fooinstâncias. Dar um nome mais significativo à classe elucida seu verdadeiro objetivo, o que provavelmente levará à refatoração.

  • Responsabilidades fracionárias

    De acordo com o princípio da responsabilidade única, cada unidade de código deve servir exatamente a um propósito. Com um gerente, você pode dividir artificialmente essa responsabilidade.

    Considere um ResourceManagerque coordena a vida útil e o acesso a Resourceinstâncias. Um aplicativo possui um único ResourceManageratravés do qual adquire Resourceinstâncias. Nesse caso, não há motivo real para que a função de uma ResourceManagerinstância não possa ser atendida por métodos estáticos na Resourceclasse.

  • Abstração não estruturada

    Freqüentemente, um gerente é apresentado para abstrair os problemas subjacentes aos objetos que gerencia. É por isso que os gerentes se prestam a abusar como curativos para sistemas mal projetados. A abstração é uma boa maneira de simplificar um sistema complexo, mas o nome "gerente" não oferece nenhuma pista sobre a estrutura da abstração que representa. É realmente uma fábrica, um proxy ou outra coisa?

Obviamente, os gerentes podem ser usados ​​para mais do que apenas o mal, pelas mesmas razões. Um EventManager- o que é realmente - Dispatcherretira os eventos das fontes e os despacha para os destinos interessados. Nesse caso, faz sentido separar a responsabilidade de receber e enviar eventos, porque um indivíduo Eventé apenas uma mensagem sem noção de proveniência ou destino.

Nós escrevemos uma Dispatcherdas Eventinstâncias pelo mesmo motivo pelo qual escrevemos a GarbageCollectorou a Factory:

Um gerente sabe o que sua carga útil não precisa saber.

Acho que essa é a melhor justificativa para a criação de uma classe gerencial. Quando você tem algum objeto de "carga útil" que se comporta como um valor, deve ser o mais estúpido possível para que o sistema geral permaneça flexível. Para fornecer significado a instâncias individuais, você cria um gerente que coordena essas instâncias de maneira significativa. Em qualquer outra situação, os gerentes são desnecessários.

Jon Purdy
fonte
3
Eu definitivamente criei classes FooManager antes. Eu também criei fábricas e proxies. Mas às vezes parece que você realmente precisa é do tipo GlorifiedCollection <Foo> e o FooManager parece se encaixar perfeitamente. Como você chamaria uma classe que literalmente gerencia a coleção interna de objetos Foo e fornece uma interface muito limpa e concisa para recuperar instâncias Foo? Acho que para mim um "gerente" é uma classe que encapsula uma fábrica (ou seja, todas as instâncias do Foo são iniciadas internamente), bem como uma coleção desses objetos. Você chamaria isso de outra coisa? Ou faz design diferente?
DXM
Ah, sim, EventDispatcherestou tentando encontrar um bom nome há um tempo. : P
Paul
@DXM Apenas para uma coleção de Foos, ele pode ser literalmente "FooList". Para o local global em que os Foos estão registrados para que possam ser recuperados mais tarde, "FooRegistry", vem à mente. Combinar coleção e fábrica não é algo que eu pessoalmente gosto de fazer, mas acredito que isso geralmente seria chamado de "FooRepository".
R. Schmitz
28

Os gerentes podem ser um sinal de uma arquitetura ruim, mas na maioria das vezes são apenas um sinal de incapacidade em nome do designer de criar nomes melhores para seus objetos, ou simplesmente um reflexo do fato de que o idioma inglês (e qualquer linguagem humana para esse assunto) é adequado para a comunicação de conceitos práticos diários, e não de conceitos altamente abstratos e técnicos.

Um exemplo simples para ilustrar meu argumento: antes que o Factory Pattern fosse nomeado, as pessoas o usavam, mas não sabiam como chamá-lo. Então, alguém que teve que escrever uma fábrica para sua Fooclasse pode ter chamado FooAllocationManager. Isso não é um design ruim, é apenas falta de imaginação.

E então alguém precisa implementar uma classe que mantenha muitas fábricas e as entregue a vários objetos que as solicitam; e ele chama sua turma FactoryManagerporque a palavra Industrynunca lhe ocorreu, ou ele pensou que não seria legal, porque ele nunca ouviu falar de algo assim na programação. Mais uma vez, um caso de falta de imaginação.

Mike Nakis
fonte
10

Ter muitas classes "gerenciador" geralmente é um sintoma de um modelo de domínio anêmico , em que a lógica do domínio é içada para fora do modelo de domínio e, em vez disso, colocada em classes gerenciadoras, que mais ou menos equivalem a scripts de transação . O perigo aqui é que você está basicamente voltando à programação procedural - que por si só pode ou não ser uma coisa boa, dependendo do seu projeto - mas o fato de não ter sido considerado ou planejado é o verdadeiro problema.

Seguindo o princípio do "especialista em informações" , uma operação lógica deve residir o mais próximo possível dos dados necessários. Isso significaria mover a lógica do domínio de volta para o modelo de domínio, para que sejam essas operações lógicas que tenham um efeito observável no estado do modelo de domínio, em vez de 'gerentes' alterando o estado do modelo de domínio de fora.

MattDavey
fonte
8

Resposta curta: depende .

Existem várias formas distintas de "classes de gerente", algumas são boas, outras são ruins e, para a maioria delas, depende muito do contexto se a introdução de uma classe de gerente é a coisa certa. Um bom ponto de partida para acertá-las é seguir o princípio da responsabilidade única - se você souber exatamente pelo que cada classe de gerente é responsável (e o que não é), você terá muito menos problemas para entendê-las.

Ou, para responder diretamente à sua pergunta: não é o número de classes de gerenciadores indicando uma arquitetura ruim, mas tendo muitas delas com responsabilidades pouco claras ou lidando com muitas preocupações.

Doc Brown
fonte
Desculpe, não considero esta resposta muito útil. Você defende que responsabilidades pouco claras e muitas preocupações são ruins. Mas isso se aplica a qualquer classe , não apenas a uma classe "Gerente". As outras respostas parecem muito mais específicas sobre como uma classe de gerentes pode ser útil ou prejudicial.
user949300
3

Embora possa ser fácil dizer que eles são inerentemente indicativos de um design ruim, eles podem servir para trazer muitos benefícios e reduzir a complexidade do código e outro código padrão no projeto, englobando uma única tarefa e responsabilidade universalmente.

Embora a prevalência de gerentes possa ser devida a um julgamento incorreto sobre o design, eles também podem ser para lidar com decisões de design inadequadas ou problemas de incompatibilidade com outros componentes em um design componente ou componentes de interface do usuário de terceiros ou serviços da web de terceiros com uma interface estranha como exemplos.

Esses exemplos demonstram onde eles são extremamente úteis para determinadas situações na redução da complexidade geral e na promoção de acoplamentos frouxos entre vários componentes e camadas, encapsulando o "código feio" em um único local. Uma dica é que as pessoas acham tentador fazer gerentes como singletons, eu desaconselharia isso, e é claro que outros sugeriram que o Princípio de Responsabilidade Única sempre deve ser seguido.

maple_shaft
fonte
2

As classes de gerente podem ser um sinal de arquitetura ruim?

Você respondeu à sua pergunta: eles não precisam ser um sinal de um design ruim.

Exceto pelo exemplo da sua pergunta com o EventManager, existe outro exemplo: no padrão de design do MVC , o apresentador pode ser visto como um gerente para as classes model / view.

No entanto, se você abusar de um conceito, é um sinal de um design ruim e, possivelmente, de uma arquitetura.

BЈовић
fonte
No corpo da pergunta - "ter muitas classes de gerente em seu design é uma coisa ruim". Acredito que é isso que o OP realmente quer saber.
Oded
2

Quando a classe tiver "Gerente" no nome, cuidado com o problema da classe de Deus (um com muitas responsabilidades). Se é difícil descrever o que uma classe é responsável com seu nome, isso é um sinal de aviso de design.

Más classes de gerente à parte, o pior nome que eu já vi foi "DataContainerAdapter"

"Dados" deve ser outro desses substrings proibidos nos nomes - são todos dados, "dados" não informa muito na maioria dos domínios.

anon
fonte
2

As classes de gerente - como quase qualquer classe que termina com "-er" - são más e não têm nada a ver com OOP. Então, para mim, é um sinal de arquitetura ruim.

Por quê? O nome "-er" implica que um designer de código executou alguma ação e a converteu em classe. Como resultado, temos uma entidade artificial que não reflete nenhum conceito tangível, mas alguma ação. Isso parece muito processual.

Além disso, normalmente essas classes pegam alguns dados e os operam. Essa é uma filosofia de dados passivos e procedimentos ativos e encontrou seu lugar na programação procedural. Se você perceber isso, não há nada ruim nas classes do Gerenciador, mas não é POO então.

O pensamento de objetos implica que os objetos fazem coisas consigo mesmos. Descubra seu domínio , construa redes semânticas , deixe seus objetos serem organismos vivos, seres humanos inteligentes e responsáveis.

Tais objetos não precisam ser controlados. Eles sabem o que fazer e como fazer. Portanto, as classes de gerente quebram os princípios de POO duas vezes. Além de ser uma classe "-er", controla outros objetos. Mas isso depende do gerente. Ele controla - ele é um mau gerente. Se ele coordena - ele é um bom gerente. É por isso que uma letra "C" no MVC deve ser escrita como "Coordenadora".

Zapadlo
fonte
Você faz uma observação interessante, mas ainda me pergunto como você classificaria um "gerente de entidade"? Da minha experiência pessoal, um gerente de <entidade> é destinado a operações CRUD em uma <entidade> específica. Isso leva o modelo de domínio a ser anêmico? Eu acho que não, apenas não "registro ativo". Além disso, não podemos colocar a lógica de coordenação CRUD dos compostos agregados de uma entidade "gerente de entidade"? Não vejo um lugar melhor para isso. Portanto, este pode ser visto como uma fachada CRUD de alguma forma também ...
ClemC
Tudo o que posso dizer sobre o concep do ORM é medium.com/@wrong.about/you-dont-need-an-orm-7ef83bd1b37d #
22417 Zapadlo
Eu não era necessário me referir às ORMs, no entanto ... Eu respeito tanto quanto posso os princípios de OO, mas parece-me que eles são bastante teóricos e nem sempre podem ser totalmente aplicados na prática ... Por exemplo, se precisamos de dissociação, reutilização, DRY, produtividade, por exemplo: colocar lógica / regras de domínio que se aplicam a diferentes entidades em serviços comuns, tornando o modelo de domínio menos comportamental ... Esse é o efeito exato de um padrão de repositório / mapeador (que você ORM você referem-se a implementar) VS um Active Record, que eu acredito que você iria favorecer ...
ClemC
1

A resposta correta para esta pergunta é:

  1. Depende.

Todas as situações que você encontra ao escrever o software são diferentes. Talvez você esteja em uma equipe onde todos sabem como as aulas de gerente funcionam internamente? Seria completamente louco não usar esse design. Ou se você está tentando enviar o design do gerente para outras pessoas, nesse caso, pode ser uma má idéia. Mas isso depende de detalhes exatos.

tp1
fonte