A capacidade de descoberta para desenvolvedores é um problema ao usar os princípios do SOLID?


10

Eu faço aplicativos de linha de negócios em que todos os outros desenvolvedores estão acostumados a criar aplicativos básicos de CRUD ou focam-se apenas em criar interfaces bonitas / funcionais e estou obtendo muito o seguinte.

"Com a maneira como usamos, o funcionário teria tudo o que você poderia fazer com um funcionário". E era verdade. Aquela "classe" tinha milhares de linhas de código e tudo o que você poderia fazer com um funcionário estava lá. Ou, pior ainda, havia uma tabela de dados de funcionários e cada desenvolvedor descobriu como fazer o que queria fazer no manipulador de eventos.

Todas as coisas ruins sobre essa abordagem eram verdadeiras, mas pelo menos o desenvolvedor que usa o funcionário poderia, sem consultar outros documentos, descobrir como inscrever o funcionário em um plano de saúde, dar um aumento de salário, demitir, contratar, transferir etc. para Manager e todas as outras idéias principais. Ou, se eles usassem o empregado em outras tabelas de dados necessárias, poderiam fazer o que quisessem.

Sim, havia muito código duplicado. Sim, era um código muito quebradiço. Sim, testar foi muito mais difícil do que o necessário. Sim, a alteração da funcionalidade foi indutora de medo e a Copy Paste foi natural devido à abordagem.

Mas eles poderiam pelo menos descobrir o que estava disponível criando uma classe ou poderiam fazer o que precisavam, sem ter que entender a diferença entre interfaces, classes abstratas, classes concretas etc. E não precisavam procurar nada além de os métodos retornados pelo intellisense ou conhecem as tabelas em que os dados residiam.

Eu pesquisei no Google / binged e até no yahoo! D, mas não encontrei nenhum reconhecimento desse problema.

Então talvez não haja um problema e só estou perdendo alguma coisa. Eu inventei meu cérebro tentando descobrir uma solução em que os desenvolvedores que não funcionam com o comportamento / design real podem descobrir facilmente como fazer algo sem ter que fazer referência a documentos externos ou verificar os nomes das classes nos vários componentes / projetos para encontrar o que parece funcionar.

A única coisa que consegui sugerir é tê-los, por falta de um nome melhor, "Classe da Tabela de Conteúdo" que nada mais faz que retornar as classes reais (e na verdade a maioria delas são interfaces, mas não conheça a diferença ou mesmo cuidado) que outros desenvolvedores podem usar para executar as tarefas desejadas. Ainda acabamos com aulas realmente grandes, mas quase não há comportamento nelas.

Existe uma maneira melhor que não exija conhecimento íntimo da camada intermediária em que a implementação real do SOLID ocorre?

Basicamente, o que estou perguntando é que existe uma maneira de permitir que os desenvolvedores do tipo CRUD continuem sendo desenvolvedores de CRUD em um sistema muito complexo


8
Talvez seus desenvolvedores não dependam inteiramente do IntelliSense (ou equivalente) para a descoberta. Nomeie bem as coisas. Documente bem as coisas. Este é um problema de comunicação, não um problema técnico.
Rein Henrichs

Hummm. Meio. Quanto mais penso nisso, mais acredito que há uma oportunidade de negócio à espreita.
ElGringoGrande 10/10

2
@ReinHenrichs: Se o desenvolvedor precisar ler a documentação, isso levará tempo e a produtividade sofrerá. Portanto, é importante que eles descubram rapidamente o que precisam para determinada tarefa. Não precisa confiar no senso comum, mas é melhor que seja fácil. Facilitar é certamente um problema técnico.
Jan Hudec 10/10

@JanHudec: Não, não é um problema técnico, mas organizacional, do uso de convenções adequadas para nomeação, layout e espaço em branco. Sem convenções de nomenclatura, você não saberia o que procurar. Sem nomes consistentes, você não encontraria tudo e / ou teria muito mais dificuldade em rastrear tudo. Sem layout consistente e uso de espaço em branco (especialmente nas declarações de tipo), você não encontraria metade das instâncias necessárias. Sim, uma regex melhor poderia ajudar, mas eu não quero aprender regex apenas para descobrir onde uma classe é usada.
Marjan Venema

@JanHudec Não é um "se", mas um "quando". Os desenvolvedores precisarão ler a documentação. Se você deseja que "descubram rapidamente o que precisam para determinada tarefa", sua melhor aposta é se concentrar em tornar a documentação eficaz. Não tente resolver um problema de pessoas (como comunicação) com uma solução técnica. Isto. Faz. Não. Trabalhos.
Rein Henrichs 10/10

Respostas:


4

Parece que o que você descreveu (por exemplo, classe Employee com TODOS os códigos possíveis que você poderia fazer com um empregado) é um padrão extremamente comum que eu já vi bastante. Parte desse código que eu escrevi antes de conhecer melhor.

O que começa como uma classe que deveria representar uma única entidade com um conjunto gerenciável de métodos, se transforma em algo que é um pesadelo a ser mantido, porque cada recurso e cada versão continuam adicionando cada vez mais à mesma classe. Isso contraria os princípios do SOLID, que dizem que você deve escrever uma classe uma vez e resistir à necessidade de modificá-la repetidamente.

Há um tempo atrás (antes de descobrir os padrões de design ou o SOLID promovido por outros), decidi para o meu próximo projeto mudar um pouco as coisas. Eu estava trabalhando em um servidor que servia como interface entre duas plataformas muito grandes. No início, era necessária apenas a sincronização da configuração, mas pude ver que esse seria um local lógico para muitos outros recursos.

Então, em vez de escrever uma classe que expôs métodos, escrevi classes que representavam métodos (acabou sendo o padrão "Command" do GoF). Em vez de fazer o trabalho para o cliente, todas as minhas principais classes de aplicativos se tornaram detentores de estado persistentes e ficaram muito mais curtos. Toda vez que eu tinha que adicionar um novo método de interface ao próprio serviço, eu simplesmente criava uma nova classe que tinha o método Execute () que iniciava tudo. Se vários comandos tinham algo em comum, eles derivavam da classe base comum. Eventualmente, a coisa tinha mais de 70 classes de comando diferentes e todo o projeto ainda era muito gerenciável e era realmente um prazer trabalhar.

Sua "classe TOC" não está muito longe do que eu fiz. Eu tinha uma fábrica abstrata (GoF) responsável por instanciar comandos. Dentro da classe factory, eu escondi a maioria dos detalhes por trás da classe base e das macros no estilo ATL; portanto, quando um programador precisava adicionar ou procurar uma solicitação, ele foi até lá e tudo o que viu foi:

BEGIN_COMMAND_MAP()
    COMMAND_ENTRY( CChangeDeviceState )
    COMMAND_ENTRY( CSetConfiguration )
    ....
END_COMMAND_MAP()

Como alternativa (ou em adição a), você pode colocar todas as suas classes de comando reais em um espaço para nome separado. Assim, quando as pessoas estão codificando e precisam executar algo, elas apenas digitam o nome do espaço para nome e o Intellisense lista todos os comandos que você definiu. Cada comando inclui todos os métodos get get / set que determinam exatamente quais parâmetros de entrada e saída.

Você também pode explorar o uso do padrão Facade (GoF). Em vez de expor mais de 1000 classes para seus engenheiros CRUD. Oculte todos eles atrás de uma única classe que expõe apenas o necessário. Eu ainda continuaria tendo cada "ação" como sua própria classe, mas sua classe Facade pode ter métodos que instanciaram cada uma de suas ações e, novamente, com o Intellisense eles veriam imediatamente o que está disponível. Ou o Facade tem métodos reais, mas internamente os faz instanciar comandos, enfileirá-los e aguardar respostas. Em seguida, retorne como se uma chamada de método regular fosse feita.

(*) Eu não queria entrar em muitos detalhes, mas na verdade tinha o conjunto de classes "Command" e "CommandHandler". Isso separava a responsabilidade de gerenciar / enfileirar / serializar parâmetros de entrada / saída de classes que realmente "manipulavam" esses comandos.


Sim. Percebi hoje que acabamos com um padrão de fachada mal implementado. Acho que não há mais nada a fazer além de quebrar a grande fachada em outras menores. Eu gosto da sua ideia de incorporar algumas classes de comando nos bastidores.
ElGringoGrande

0

Isso pode ser um problema. Especialmente se você nomear as coisas mal. Mas existem várias soluções para isso sem recorrer a classes complexas. Caramba, uma classe com muitos métodos pode ser igualmente difícil de navegar com o Intellisense.

Tente usar namespaces (C #) ou pacotes (Java), ou qualquer conceito semelhante que sua linguagem tenha (vou me referir a todos eles como namespaces), para simplificar o problema.

Comece com o nome da sua empresa. Isso limita o Intellisense a apenas namespaces escritos por vocês. Em seguida, se você tiver vários aplicativos, use a segunda parte do espaço para nome para dividi-los. Inclua um namespace Core, para coisas que existem entre aplicativos. Em seguida, divida as coisas em tipos de funcionalidade. E assim por diante.

Se você fizer isso direito, terá itens muito detectáveis.

Para dar o seu exemplo, se eu quiser a validação do usuário, digite "MyCo". e isso me fornece uma lista de namespaces de aplicativos. Sei que o banco de dados do usuário é usado em todos os nossos aplicativos, então digito "Core". então eu recebo uma lista de tipos de funcionalidade. Um deles é "Validação", de modo que parece uma escolha óbvia. E, dentro da Validação, existe o "UserValidator" com todas as suas funcionalidades.

Por acaso, nas coisas que uso muito, lembrarei rapidamente dos nomes, ou pelo menos das convenções. Como faço muitas alterações nas regras de validação, saberei que todas as minhas classes de validação são chamadas FooValidator, onde Foo é o nome da tabela. Então, na verdade, não precisarei percorrer os espaços para nome. Vou apenas digitar UserValidator e deixar o IDE fazer o resto do trabalho.

Mas para coisas que não me lembro, ainda é muito fácil encontrá-las. E quando eu faço, posso remover o prefixo do espaço para nome.


É, em parte, uma má nomeação para mim. Os nomes não são horríveis, mas muitas vezes penso em um mês melhor após o fato. Mas mesmo com bons nomes, se você tiver milhares de classes, os nomes nem sempre são fáceis de descobrir. Eu estou tentando superar isso. Eu apenas pensei que poderia haver uma maneira conhecida.
ElGringoGrande 10/10

0

Como você os refere como desenvolvedores basicamente "CRUD", presumimos que você não os considera muito bons. Não sabemos se isso significa que eles também não entendem o domínio da sua empresa. Se eles entenderem o domínio, as classes deverão fazer sentido para elas. Sabendo que várias classes foram criadas, elas devem dar uma olhada primeiro, perguntar em segundo lugar, considerar a construção do zero como uma terceira opção.

Tanto quanto saber como automaticamente usar / reutilizar uma classe apenas olhando para ela, não deve ser esperado na primeira vez. Você precisará documentar e possivelmente fornecer explicações adicionais por meio de treinamento ou possivelmente durante a revisão de código.

Muitos APIs e projetos de código aberto fornecem documentação, exemplos de código e outras explicações. O seu talvez não precise ser tão amigável, mas não há como contornar isso. Ensine-os bem.


Não. CRUD não significa que eles não são bons. Eles são desenvolvedores que sempre lidaram com aplicativos de dados básicos. CRUD = criar, ler, atualizar e excluir. Não vejo como isso os torna maus programadores.
ElGringoGrande 10/10

Na gíria inglesa britânica, "crud" == "merda".
22611 Michael Shaw
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.