Por que precisamos de tantas classes em padrões de design?

209

Sou desenvolvedor júnior entre os idosos e estou lutando muito com a compreensão de seus pensamentos, raciocínios.

Estou lendo DDD ( Domain-Driven Design ) e não consigo entender por que precisamos criar tantas classes. Se seguirmos esse método de criação de software, terminaremos com 20 a 30 classes que podem ser substituídas por no máximo dois arquivos e 3-4 funções. Sim, isso pode ser confuso, mas é muito mais sustentável e legível.

Sempre que eu quiser ver o que algum tipo de ação EntityTransformationServiceImplfaz, preciso seguir muitas classes, interfaces, suas chamadas de função, construtores, sua criação e assim por diante.

Matemática simples:

  • 60 linhas de código fictício vs 10 classes X 10 (digamos que tenhamos lógicas totalmente diferentes) = 600 linhas de código confuso vs. 100 classes + mais algumas para envolvê-las e gerenciá-las; não esqueça de adicionar injeção de dependência.
  • Lendo 600 linhas de código confuso = um dia
  • 100 aulas = uma semana, ainda se esqueça de quem faz o quê, quando

Todo mundo está dizendo que é fácil de manter, mas para quê? Toda vez que você adiciona novas funcionalidades, adiciona mais cinco classes com fábricas, entidades, serviços e valores. Eu sinto que esse tipo de código se move muito mais devagar que o código confuso.

Digamos que, se você escrever um código confuso de 50K LOC em um mês, o DDD precisará de várias revisões e alterações (eu não me importo com os testes nos dois casos). Uma simples adição pode levar uma semana, se não mais.

Em um ano, você escreve muitos códigos confusos e pode reescrevê-los várias vezes, mas com o estilo DDD, você ainda não possui recursos suficientes para competir com códigos confusos.

Por favor explique. Por que precisamos desse estilo DDD e de muitos padrões?

UPD 1 : Eu recebi tantas respostas ótimas, vocês podem adicionar um comentário em algum lugar ou editar sua resposta com o link para a lista de leitura (não sei por onde começar, DDD, Design Patterns, UML, Code Complete, Refactoring, Pragmatic,. ... tantos bons livros), é claro com sequência, para que eu também possa começar a entender e me tornar mais velho, como alguns de vocês.

user1318496
fonte
81
Acho que há uma boa pergunta aqui, mas ela está escondida por trás da hipérbole e da frustração. @ user1318496, você pode se beneficiar de reformular sua pergunta um pouco.
MetaFight 10/04
48
Correndo o risco de pisar no pé, porque seu idioma é péssimo. Não tome isso por mais do que é: um idioma ruim é muitas vezes a escolha técnica correta por várias razões, mas isso não o torna ruim. Quanto à sua pergunta real, a correção é mais importante que a legibilidade. Ou, para dizer um pouco diferente: a legibilidade é importante na medida em que permite raciocinar sobre a correção. Então, o que é mais fácil de testar, suas 100 classes ou sua classe divina monolítica? Estou apostando 100 aulas simples.
Jared Smith
87
"Sim, isso pode ser confuso, mas é muito mais sustentável e legível.". Se estiver bagunçado, como pode ser legível e sustentável?
Polygnome
37
@ Polygnome: Eu estava prestes a digitar exatamente o mesmo comentário. Outra característica de comentário de escolha dos desenvolvedores juniores é "Eu sinto que esse tipo de código se move muito mais devagar que o código bagunçado". Não adianta correr o mais rápido possível, se você gastar metade do seu tempo correndo contra as paredes! Devagar é suave, suave é rapido.
precisa
40
Você não, a menos que esteja fazendo Java. Quando tudo que você tem é Java, tudo parece uma classe.
precisa saber é

Respostas:

336

Este é um problema de otimização

Um bom engenheiro entende que um problema de otimização não tem sentido sem um alvo. Você não pode simplesmente otimizar, você precisa otimizar para alguma coisa. Por exemplo, suas opções do compilador incluem otimizar a velocidade e otimizar o tamanho do código; esses são objetivos às vezes opostos.

Gosto de dizer à minha esposa que minha mesa está otimizada para acrescentar. É apenas uma pilha e é muito fácil adicionar coisas. Minha esposa preferiria que eu otimizasse a recuperação, ou seja, organizei um pouco minhas coisas para que eu pudesse encontrar as coisas. Isso dificulta, é claro, adicionar.

Software é da mesma maneira. Você certamente pode otimizar a criação de produtos - gerar uma tonelada de código monolítico o mais rápido possível, sem se preocupar em organizá-lo. Como você já notou, isso pode ser muito, muito rápido. A alternativa é otimizar para manutenção - tornar a criação um toque mais difícil, mas tornar as modificações mais fáceis ou menos arriscadas. Esse é o objetivo do código estruturado.

Eu sugeriria que um produto de software de sucesso fosse criado apenas uma vez, mas modificado muitas e muitas vezes. Engenheiros experientes viram bases de código não estruturadas ganhar vida própria e tornarem-se produtos, crescendo em tamanho e complexidade, até que pequenas mudanças são muito difíceis de serem feitas sem introduzir um grande risco. Se o código foi estruturado, o risco pode ser contido. É por isso que vamos a todo esse problema.

Complexidade vem de relações, não de elementos

Percebo na sua análise que você está analisando quantidades - quantidade de código, número de classes, etc. Embora isso seja interessante, o impacto real vem das relações entre os elementos, que explodem combinatoriamente. Por exemplo, se você tem 10 funções e não tem idéia de qual depende, você tem 90 relações possíveis (dependências) com as quais precisa se preocupar - cada uma das dez funções pode depender de qualquer uma das nove outras funções e 9 x 10 = 90. Você pode não ter idéia de quais funções modificam quais variáveis ​​ou como os dados são transmitidos, para que os codificadores tenham um monte de coisas com que se preocupar ao resolver qualquer problema específico. Por outro lado, se você tem 30 classes, mas elas são organizadas de maneira inteligente, elas podem ter apenas 29 relações, por exemplo, se estiverem em camadas ou organizadas em uma pilha.

Como isso afeta o rendimento da sua equipe? Bem, há menos dependências, o problema é muito mais tratável; os programadores não precisam manipular um zilhão de coisas na cabeça sempre que fazem uma alteração. Portanto, minimizar as dependências pode ser um grande impulso à sua capacidade de raciocinar sobre um problema de forma competente. É por isso que dividimos as coisas em classes ou módulos, e as variáveis ​​de escopo da forma mais rígida possível e usamos os princípios do SOLID .

John Wu
fonte
103
Eu observaria, no entanto, que uma superabundância de classes e indiretos NÃO ajudam a entender a manutenção da NOR. E nem fluxos de controle complicados (também conhecido como inferno de retorno de chamada).
Matthieu M.
9
@ JohnWu esta explicação é a melhor e mais fácil de entender que eu já li.
Adriano Repetti
13
Bem escrito, mas talvez esteja faltando por que "criado uma vez, mas modificado muitas e muitas vezes" é importante? (Se todo o código estiver inserido EntityTransformationServiceImpl, você será obrigado a aprender como tudo funciona antes de corrigi-lo - mas se, por exemplo, algo estiver errado com o formato e uma Formatterclasse lidar com isso, você só precisará aprender como essa parte funciona . ler o seu próprio código após ~ 3 meses é como ler o código de um estranho.) Sinto que a maioria de nós subconscientemente pensou nisso, mas isso pode ser por causa da experiência. Não tenho 100% de certeza disso.
R. Schmitz
17
Eu usaria 10 × 10 = 100 completos para a combinatória: essas funções poderiam muito bem ser recursivas e, em código particularmente ruim, não necessariamente óbvio.
KRyan #
32
"A alternativa é otimizar a manutenção - tornar a criação um toque mais difícil, mas tornar as modificações mais fáceis ou menos arriscadas. Esse é o objetivo do código estruturado". Eu discordo da noção implícita de que mais classes = mais manutenibilidade. Em particular, a dispersão da lógica por muitas classes geralmente dificulta a localização dos conceitos lógicos abrangentes no código (especialmente sem um olho muito intencional em garantir que os conceitos sejam muito visíveis), o que prejudica enormemente a capacidade de manutenção.
precisa saber é o seguinte
67

Bem, antes de tudo, a legibilidade e a manutenção estão frequentemente nos olhos de quem vê.

O que é legível para você pode não ser para o seu vizinho.

A capacidade de manutenção geralmente se resume à capacidade de descoberta (com que facilidade um comportamento ou conceito é descoberto na base de código) e a capacidade de descoberta é outra coisa subjetiva.

DDD

Uma das maneiras pelas quais o DDD ajuda as equipes de desenvolvedores é sugerir uma maneira específica (ainda subjetiva) de organizar seus conceitos e comportamentos de código. Essa convenção facilita a descoberta de coisas e, portanto, a manutenção do aplicativo.

  • Os conceitos de domínio são codificados como Entidades e Agregados
  • O comportamento do domínio reside em Entidades ou Serviços de Domínio
  • A consistência é assegurada pelas Raízes Agregadas
  • As preocupações de persistência são tratadas pelos repositórios

Esse arranjo não é objetivamente mais fácil de manter. No entanto, é mensurável mais fácil de manter quando todos entendem que estão operando em um contexto DDD.

Aulas

As aulas ajudam na manutenção, legibilidade, descoberta, etc ... porque são uma convenção bem conhecida .

Nas configurações orientadas a objetos, as Classes geralmente são usadas para agrupar comportamentos estreitamente relacionados e encapsular o estado que precisa ser controlado com cuidado.

Sei que parece muito abstrato, mas você pode pensar assim:

Com Classes, você não precisa necessariamente saber como o código nelas funciona. Você só precisa saber pelo que a turma é responsável.

As classes permitem que você raciocine sobre seu aplicativo em termos de interações entre componentes bem definidos .

Isso reduz a carga cognitiva ao raciocinar sobre como seu aplicativo funciona. Em vez de ter que lembrar o que 600 linhas de código realizam, você pode pensar em como 30 componentes interagem.

E, considerando que esses 30 componentes provavelmente abrangem 3 camadas de seu aplicativo, você provavelmente apenas deve raciocinar sobre aproximadamente 10 componentes por vez.

Isso parece bastante administrável.

Sumário

Essencialmente, o que você está vendo os desenvolvedores seniores fazerem é o seguinte:

Eles estão dividindo o aplicativo em fácil raciocínio sobre classes.

Em seguida, eles estão organizando-os para facilitar o raciocínio sobre as camadas.

Eles estão fazendo isso porque sabem que, à medida que o aplicativo cresce, fica cada vez mais difícil argumentar sobre isso como um todo. Dividi-lo em Camadas e Classes significa que eles nunca precisam raciocinar sobre o aplicativo inteiro. Eles só precisam raciocinar sobre um pequeno subconjunto dele.

MetaFight
fonte
5
Além das classes menores, é mais fácil substituir / refatorar.
Zalomon
12
A superengenharia não fornece um código mais sustentável ou compreensível - pelo contrário, apesar do que você afirma. Quem precisa de um AddressServiceRepositoryProxyInjectorResolverquando você pode resolver o problema com mais elegância? Padrões de design por causa dos padrões de design apenas levam a complexidade e verbosidade desnecessárias.
vikingsteve
27
Sim, a superengenharia é ruim. O mesmo acontece com matar filhotes. Ninguém aqui está defendendo nenhum dos dois. logicallyfallacious.com/tools/lp/Bo/LogicalFallacies/169/…
MetaFight 11/18
5
Além disso, "elegância" no contexto de engenharia de software é frequentemente uma palavra Weasel. en.wikipedia.org/wiki/Weasel_word
MetaFight
11
O mesmo poderia ser dito de qualquer abordagem para organizar o código. Tudo depende da equipe de manutenção entender por que o código está organizado como está. Esse é o objetivo de usar convenções bem estabelecidas e compreendidas.
MetaFight 11/04
29

Por favor, explique-me, por que precisamos desse estilo DDD, muitos padrões?

Primeiro, uma observação: a parte importante do DDD não são os padrões , mas o alinhamento do esforço de desenvolvimento com os negócios. Greg Young observou que os capítulos do livro azul estão na ordem errada .

Mas para sua pergunta específica: há muito mais classes do que você esperaria, (a) porque está sendo feito um esforço para distinguir o comportamento do domínio do encanamento e (b) porque está sendo feito um esforço extra para garantir que os conceitos no modelo de domínio são expressos explicitamente.

Sem rodeios, se você tiver dois conceitos diferentes no domínio, eles deverão ser distintos no modelo, mesmo que compartilhem o mesmo na representação de memória .

Com efeito, você está criando uma linguagem específica de domínio que descreve seu modelo no idioma da empresa, de forma que um especialista em domínio possa examiná-lo e detectar erros.

Além disso, você vê um pouco mais de atenção dada à separação de preocupações; e a noção de isolar consumidores de alguma capacidade a partir dos detalhes da implementação. Veja DL Parnas . Os limites claros permitem que você altere ou estenda a implementação sem que os efeitos se espalhem por toda a solução.

A motivação aqui: para um aplicativo que faz parte da competência principal de uma empresa (ou seja, um local em que obtém uma vantagem competitiva), você poderá substituir de forma fácil e barata um comportamento de domínio por uma variação melhor. De fato, você tem partes do programa que deseja evoluir rapidamente (como o estado evolui com o tempo) e outras partes que deseja alterar lentamente (como o estado é armazenado); as camadas extras de abstração ajudam a evitar acoplar inadvertidamente uma à outra.

Para ser justo: alguns deles também são danos cerebrais orientados a objetos. Os padrões originalmente descritos por Evans são baseados em projetos Java dos quais ele participou há mais de 15 anos; estado e comportamento estão fortemente associados a esse estilo, o que leva a complicações que você pode preferir evitar; veja Percepção e ação, de Stuart Halloway, ou Inlining Code, de John Carmack.

Não importa em que idioma você trabalha, a programação em um estilo funcional oferece benefícios. Você deve fazê-lo sempre que for conveniente e deve pensar bastante sobre a decisão quando ela não for conveniente. Carmack, 2012

VoiceOfUnreason
fonte
2
Eu adicionaria minha própria resposta até ler isso. Eu enfatizaria o primeiro parágrafo, que o objetivo é modelar conceitos de negócios em software para alinhar o software aos requisitos de negócios. Para ser justo, o analista que dirige o projeto também deve expressar quanto tempo o motorista leva para a entrega e a qualidade ou integridade do código / teste deve ser ajustada de acordo.
Sentinel
1
John Carmack é um ótimo exemplo de IMO, já que ele é conhecido por escrever código limpo e fácil de entender, além de ter um bom desempenho. Isso é especialmente visível quando você acompanha o código com tecnologias avançadas - com melhores CPUs e memória, você pode ver muitas coisas empurradas de "isso precisa ser realmente conciso" para "isso precisa ser realmente claro / isolado / ... " Um dos programadores mais pragmáticas que eu conheço :)
Luaan
Eu acho que esta é a melhor resposta aqui. Embora eu não seja vendido de maneira alguma ao DDD, essa resposta certamente explica pelo menos o que realmente é e uma motivação real para ela, em vez de apelar para banalidades comuns que não significam nada.
perfil completo de jpmc26
29

Existem muitos pontos positivos nas outras respostas, mas acho que eles perdem ou não enfatizam um importante erro conceitual que você comete:

Você está comparando o esforço para entender o programa completo.

Esta não é uma tarefa realista com a maioria dos programas. Mesmo programas simples consistem em tanto código que é simplesmente impossível gerenciar tudo na cabeça a qualquer momento. Sua única chance é encontrar a parte de um programa que é relevante para a tarefa em questão (consertar um bug, implementar um novo recurso) e trabalhar com isso.

Se o seu programa consiste em grandes funções / métodos / classes, isso é quase impossível. Você precisará entender centenas de linhas de código apenas para decidir se esse pedaço de código é relevante para o seu problema. Com as estimativas que você forneceu, fica fácil passar uma semana apenas para encontrar o trecho de código em que você precisa trabalhar.

Compare isso com uma base de código com pequenas funções / métodos / classes nomeadas e organizadas em pacotes / espaços para nome que tornam óbvio onde encontrar / colocar uma determinada parte da lógica. Quando bem feito, em muitos casos, você pode pular direto para o local correto para resolver seu problema, ou pelo menos para um local de onde o acionador do depurador o levará ao local certo em alguns saltos.

Eu trabalhei nos dois tipos de sistemas. A diferença pode ser facilmente duas ordens de magnitude no desempenho para tarefas comparáveis ​​e tamanho de sistema comparável.

O efeito que isso tem em outras atividades:

  • o teste se torna muito mais fácil com unidades menores
  • menos conflitos de mesclagem porque as chances de dois desenvolvedores trabalharem no mesmo trecho de código são menores.
  • menos duplicação porque é mais fácil reutilizar peças (e encontrar as peças em primeiro lugar).
Jens Schauder
fonte
19

Porque testar código é mais difícil do que escrever código

Muitas respostas deram um bom raciocínio da perspectiva de um desenvolvedor - que a manutenção pode ser reduzida, com o custo de tornar o código mais árduo para escrever em primeiro lugar.

No entanto, há outro aspecto a considerar - o teste só pode ser refinado como seu código original.

Se você escreve tudo em um monólito, o único teste eficaz que você pode escrever é "dadas essas entradas, a saída está correta?". Isso significa que todos os erros encontrados têm o escopo definido como "em algum lugar nessa pilha gigante de código".

Obviamente, você pode ter um desenvolvedor sentado com um depurador e descobrir exatamente onde o problema começou e trabalhar em uma correção. Isso requer muitos recursos e é um mau uso do tempo de um desenvolvedor. Imagine que um bug cada vez menor, resulta em um desenvolvedor precisando depurar todo o programa novamente.

A solução: muitos testes menores que identificam uma falha específica em potencial cada.

Esses pequenos testes (por exemplo, testes de unidade) têm a vantagem de verificar uma área específica da base de código e ajudar a encontrar erros dentro de um escopo limitado. Isso não apenas acelera a depuração quando um teste falha, mas também significa que, se todos os seus pequenos testes falharem - você poderá encontrar mais facilmente a falha nos testes maiores (ou seja, se não estiver em uma função específica testada, deverá estar na interação entre eles).

Como deve ficar claro, para fazer testes menores, sua base de código precisa ser dividida em pequenos pedaços testáveis. A maneira de fazer isso, em uma grande base de código comercial, geralmente resulta em código parecido com o que você está trabalhando.

Apenas como uma nota lateral: isso não quer dizer que as pessoas não levem as coisas "longe demais". Mas há uma razão legítima para separar as bases de código em partes menores / menos conectadas - se isso for feito com sensatez.

Bilkokuya
fonte
5
Enquanto sua resposta aborda apenas testes e testabilidade, essa é a questão mais importante que algumas das outras respostas ignoraram completamente.
Skomisa 11/04/19
17

Por favor, explique-me, por que precisamos desse estilo DDD, muitos padrões?

Muitos (a maioria ...) de nós realmente não precisam deles. Teóricos e programadores experientes e muito avançados escrevem livros sobre teorias e metodologias como resultado de muitas pesquisas e sua profunda experiência - isso não significa que tudo o que escrevem seja aplicável a todos os programadores em sua prática cotidiana.

Como desenvolvedor júnior, é bom ler livros como o que você mencionou para ampliar suas perspectivas e informá-lo sobre certos problemas. Isso também evitará que você se sinta envergonhado e confuso quando seus colegas mais velhos usam a terminologia que você não conhece. Se você encontrar algo muito difícil e não parece fazer sentido ou parecer útil, não se mate por isso - basta arquivar na sua cabeça que existe esse conceito ou abordagem.

No seu desenvolvimento do dia a dia, a menos que você seja um acadêmico, seu trabalho é encontrar soluções viáveis ​​e sustentáveis. Se as idéias encontradas em um livro não o ajudarem a atingir esse objetivo, não se preocupe com isso agora, desde que seu trabalho seja considerado satisfatório.

Pode chegar um momento em que você descobrirá que pode usar parte do que leu, mas não conseguiu "entender" a princípio, ou talvez não.

Vetor
fonte
12
Embora em um nível puro, isso esteja correto, parece que DDD e outros padrões são apenas teoria. Eles não são. São ferramentas importantes para obter código legível e de manutenção.
Jens Schauder
9
@PeteKirkham, o dilema dos OPs é o uso excessivo de padrões de design. Você realmente precisa de um AccountServiceFacadeInjectResolver(exemplo real que acabei de encontrar em um sistema em funcionamento) - a resposta provavelmente não é.
vikingsteve
4
O @vikingsteve OP não é um guru da programação comentando o uso excessivo geral de padrões de design. OP é um aprendiz e acha que eles estão sendo usados ​​demais em sua loja . Eu sei que iniciante - eu teria pensado o mesmo sobre o código que escrevo hoje em dia, mas iniciante - eu teve muitos projetos pessoais que falharam porque acabaram muito complicados.
R. Schmitz
3
@ R.Schmitz Dito isto, para mim, iniciantes, muitos projetos pessoais falharam porque se esforçaram demais para tornar as coisas bem projetadas, organizadas, estruturadas, OOP ... Todas essas são ferramentas. Eles precisam ser entendidos e usados ​​corretamente, e você dificilmente pode culpar o martelo por ser pobre em ferrar. Surpreendentemente, parece ter um monte de visão e experiência para entender esta coisa simples :)
Luaan
3
@Luaan Se você já se importava com OOP bem projetado, organizado, estruturado, dificilmente chamaria isso de iniciante - você, mas sim, o uso excessivo é ruim. No entanto, a questão é mais sobre como o OP realmente não entende quais problemas essas coisas resolvem. Se você não sabe o motivo, parece que não há motivo - mas, na verdade, você ainda não o conhece.
R. Schmitz
8

Como sua pergunta está cobrindo muito terreno, com muitas suposições, vou destacar o assunto da sua pergunta:

Por que precisamos de tantas classes em padrões de design

Nós não. Não existe uma regra geralmente aceita que diga que deve haver muitas classes nos padrões de design.

Existem dois guias principais para decidir onde colocar o código e como cortar suas tarefas em diferentes unidades de código:

  • Coesão: qualquer unidade de código (seja um pacote, um arquivo, uma classe ou um método) deve pertencer um ao outro . Ou seja, qualquer método específico deve ter uma tarefa e fazer isso bem. Qualquer classe deve ser responsável por um tópico maior (o que quer que seja). Queremos alta coesão.
  • Acoplamento: quaisquer duas unidades de código devem depender o mínimo possível uma da outra - especialmente não deve haver dependências circulares. Queremos baixo acoplamento.

Por que esses dois devem ser importantes?

  • Coesão: um método que faz muitas coisas (por exemplo, um script CGI antiquado que faz GUI, lógica, acesso ao banco de dados etc. tudo em uma longa confusão de código) se torna pesado. No momento da redação deste artigo, é tentador apenas colocar sua linha de pensamento em um método longo. Isso funciona, é fácil de apresentar e tal, e você pode fazer isso. O problema surge mais tarde: depois de alguns meses, você pode esquecer o que fez. Uma linha de código na parte superior pode estar a algumas telas de uma linha na parte inferior; é fácil esquecer todos os detalhes. Qualquer alteração em qualquer parte do método pode interromper qualquer quantidade de comportamentos da coisa complexa. Será bastante complicado refatorar ou reutilizar partes do método. E assim por diante.
  • Acoplamento: sempre que você altera uma unidade de código, potencialmente interrompe todas as outras unidades que dependem dela. Em linguagens estritas como Java, você pode obter dicas durante o tempo de compilação (ou seja, sobre parâmetros, exceções declaradas e assim por diante). Mas muitas mudanças não estão provocando tais mudanças (ou seja, mudanças comportamentais) e outras linguagens mais dinâmicas não têm essas possibilidades. Quanto maior o acoplamento, mais difícil é mudar alguma coisa e você pode parar, onde é necessária uma reescrita completa para atingir algum objetivo.

Esses dois aspectos são os "drivers" básicos para qualquer escolha de "onde colocar o quê" em qualquer linguagem de programação e em qualquer paradigma (não apenas no OO). Nem todo mundo está explicitamente ciente deles, e leva tempo, muitas vezes anos, para obter uma sensação realmente arraigada e automática de como isso influencia o software.

Obviamente, esses dois conceitos não dizem nada sobre o que realmente fazer . Algumas pessoas erram do lado de muito, outras do lado de muito pouco. Algumas linguagens (olhando para você aqui, Java) tendem a favorecer muitas classes devido à natureza extremamente estática e pedante da própria linguagem (isso não é uma declaração de valor, mas é o que é). Isso se torna especialmente perceptível quando você o compara com linguagens dinâmicas e mais expressivas, por exemplo, Ruby.

Outro aspecto é que algumas pessoas aderem à abordagem ágil de apenas escrever código necessário no momento e refatorar mais tarde, quando necessário. Nesse estilo de desenvolvimento, você não criaria um interfacequando tiver apenas uma classe de implementação. Você simplesmente implementaria a classe concreta. Se, mais tarde, você precisar de uma segunda classe, refatoraria.

Algumas pessoas simplesmente não funcionam dessa maneira. Eles criam interfaces (ou, geralmente, classes básicas abstratas) para qualquer coisa que possa ser usada de maneira mais geral; isso leva a uma explosão de classe rapidamente.

Novamente, existem argumentos a favor e contra, e não importa qual eu ou você prefira. Em sua vida como desenvolvedor de software, você encontrará todos os extremos, desde métodos longos de espaguete, passando por projetos de classe iluminados e com tamanho suficiente, até esquemas de classe incrivelmente ampliados e com muita engenharia. À medida que for adquirindo experiência, você se tornará mais um papel "arquitetônico" e poderá começar a influenciar isso na direção que deseja. Você descobrirá um meio de ouro para si mesmo e continuará descobrindo que muitas pessoas vão discordar de você, faça o que fizer.

Portanto, manter uma mente aberta é a parte mais importante aqui, e esse seria o meu conselho principal para você, visto que você parece sentir muita dor com o problema, a julgar pelo resto da sua pergunta ...

AnoE
fonte
7

Codificadores experientes aprenderam:

  • Porque esses programas pequenos e sem classe começam a crescer, especialmente os bem-sucedidos. Os padrões simples que funcionavam em um nível simples não são escaláveis.
  • Porque pode parecer oneroso adicionar / alterar vários artefatos para cada adição / alteração, mas você sabe o que adicionar e é fácil fazê-lo. 3 minutos de digitação superam 3 horas de codificação inteligente.
  • Muitas turmas pequenas não são "confusas" só porque você não entende por que a sobrecarga é realmente uma boa ideia
  • Sem o conhecimento do domínio adicionado, o código "óbvio para mim" é muitas vezes misterioso para os meus companheiros de equipe ... além do futuro para mim.
  • O conhecimento tribal pode tornar os projetos incrivelmente difíceis de adicionar aos membros da equipe com facilidade e dificuldade para que eles sejam produtivos rapidamente.
  • A nomeação é um dos dois problemas difíceis da computação ainda é verdade, e muitas classes e métodos costumam ser um exercício intenso de nomeação, o que muitos consideram um grande benefício.
Michael Durrant
fonte
5
Mas a sobrecarga é necessária? Em muitos casos que vejo, os padrões de design são usados ​​em excesso. O resultado do excesso de complexidade aumenta a dificuldade de entender, manter, testar e depurar códigos. Quando você tem 12 classes e 4 módulos de preparação em torno de uma classe de serviço simples (um exemplo real que acabei de ver), rapidamente se torna menos gerenciável do que você imagina.
vikingsteve
4
@vikingsteve Você continua se referindo a um único exemplo de implementação falha, na esperança de provar que o código estruturado, em geral, é uma má idéia. Isso simplesmente não acompanha.
MetaFight 11/04
2
O @MetaFight OP não está falando sobre código de estrutura. Ele está falando sobre o que ele vê como muitas abstrações. Se você tem muitas abstrações, eu argumento, você obtém rapidamente um código muito não estruturado e muitas peças quase idênticas, simplesmente porque as pessoas não conseguem lidar com a quantidade de coisas com as quais precisam lidar.
Clearer
4
@ Clearer Tenho certeza de que todos aqui estão de acordo em que a hipotética aplicação incorreta de código estruturado é uma coisa ruim. O OP diz que eles são Júnior. É por isso que as pessoas estão assumindo que ele / ela não está familiarizado com os benefícios do código estruturado e reiterando-os.
MetaFight 12/04
2

As respostas até agora, todas elas boas, começaram com a suposição razoável de que o autor está faltando alguma coisa, o que o autor também reconhece. Também é possível que o solicitante esteja basicamente certo, e vale a pena discutir como essa situação pode ocorrer.

A experiência e a prática são poderosas, e se os idosos obtiveram experiência em projetos grandes e complexos, onde a única maneira de manter as coisas sob controle é com muitos EntityTransformationServiceImpl, eles se tornam rápidos e confortáveis ​​com os padrões de design e a estreita adesão ao DDD. Eles seriam muito menos eficazes usando uma abordagem leve, mesmo para programas pequenos. Como o estranho, você deve se adaptar e será uma ótima experiência de aprendizado.

Embora se adapte, você deve entender isso como uma lição no equilíbrio entre aprender profundamente uma única abordagem, a ponto de fazê-la funcionar em qualquer lugar, em vez de permanecer versátil e saber quais ferramentas estão disponíveis sem necessariamente ser um especialista em qualquer uma delas. Existem vantagens para ambos e ambos são necessários no mundo.

Josh Rumbut
fonte
-4

Tornar mais classe e função conforme o uso será uma ótima abordagem para resolver problemas de uma maneira específica que ajudará no futuro a resolver quaisquer problemas.

Várias classes ajudam a identificar como seu trabalho básico e qualquer classe pode ser chamada a qualquer momento.

No entanto, se você tiver muitas classes e funções a partir do nome de obtenção, elas serão fáceis de chamar e gerenciar. Isso é chamado de código limpo.

Sanjeev Chauhan
fonte
9
Desculpe, mas o que você está dizendo?
Deduplicator
@ Deduplicator vamos dar um exemplo em java, se projetarmos, usamos threads e classes jframes para sua herança. A partir de apenas uma classe que não pode capaz de usar algumas obras de java para o projeto assim que nós precisamos de fazer mais aulas
Sanjeev Chauhan
2
Essa resposta precisa apresentar a (s) idéia (s) que pretende apresentar em inglês mais claro. Parece que a idéia principal da resposta é que classes menores, cada uma com uma funcionalidade bem definida, é uma boa idéia, mas a gramática terrível torna quase impossível entender. Além disso, por si só, essa afirmação pode não ser suficiente.
talonx