Como realmente descobrir o que deve ser feito no design orientado a objetos?

12

Primeiro um aviso: eu realmente não sei se essa pergunta se encaixa neste site, mas ainda acho uma questão relevante não apenas para mim, mas para outras pessoas que são iniciantes. Se a pergunta puder ser aprimorada para caber aqui, aponte os comentários. Se não se encaixar, informe-me também e, se possível, informe onde isso pode ser discutido, porque não encontrei bons fóruns para isso.

Aprendi a programar em 2009 quando estudei PHP. Mais tarde, em 2012, mudei para C # e .NET. Enfim, codificar não é o problema, escrever algoritmos não é problema meu. Meu problema real é saber o que deve ser codificado para atingir um requisito e onde ele deve ser codificado.

A maioria dos cursos disponíveis na Web aborda como - como escrever código em um determinado idioma, como usar alguns conjuntos de APIs, etc. Esse não é o meu ponto aqui.

Nestes anos, li muito sobre várias coisas: análise e design orientados a objetos, padrões de design, design orientado a domínio e assim por diante. Entendo, por exemplo, os princípios do SOLID, algumas das principais idéias do DDD, como a necessidade de envolvimento de especialistas em domínio, o desenvolvimento de uma linguagem onipresente e assim por diante. Ousaria dizer que tenho uma base teórica pelo menos razoável.

Mas quando se trata de praticar, sinto que sou um desastre. Algum tempo atrás, eu precisava continuar o desenvolvimento de um sistema financeiro que já estava sendo desenvolvido por outra pessoa. É esse tipo de "sistema antigo" desenvolvido com C # e WinForms. Foi a primeira vez que escolhi um projeto com complexidade de domínio real, com muitas regras de negócios e assim por diante.

Confesso que, quando recebo os requisitos na maioria das vezes, penso "como isso pode ser feito?" - Eu não tenho idéia de como começar a trabalhar nos requisitos para descobrir o que deve ser feito. Minhas principais confusões, acredito, são o que devo codificar, que classes, interfaces e para onde vai cada parte da lógica, em qual classe cada coisa deve estar. O problema é que não sei por onde começar.

Na maioria das vezes, com muito pensamento, acabo com algumas idéias, mas nunca sei como julgar se minha ideia está correta ou não.

Quero dizer, não acho que seja uma falta de teoria, pois disse que li sobre um monte de coisas sobre arquitetura de software e orientação a objetos que me foram recomendadas, mas não ajudou muito a identificar o que deve ser feito na prática. .

Então, como posso aprender a realmente fazer design orientado a objetos? O que eu quero aprender é: dado que os requisitos sabem como começar a trabalhar neles em um processo que leva a descobrir o que precisa ser feito e aonde cada parte do código pertence. Como também posso aprender a julgar se minha ideia está correta ou não?

Acredito que explicar completamente isso como resposta aqui não seria possível. O que eu estou procurando, no entanto, que possa estar de acordo com o estilo do site, são respostas que dão uma visão geral e apontam algumas referências (livros, cursos on-line, etc.) que podem ser usadas para expandir as idéias e realmente aprender essas coisas.

user1620696
fonte
1. Você já entende todos os conceitos fundamentais de C #, incluindo coisas como a diferença entre sobrecarga de operador e substituição de operador, o que é uma classe abstrata e como é diferente de uma interface, encapsulamento, polimorfismo etc.? Conhecer essas coisas primeiro é essencial para entender completamente o OO em C #. Consulte c-sharpcorner.com/technologies/oop-ood .
Robert Harvey
2
2. Aplicativos mais antigos escritos em Winforms tendem a se transformar em grandes bolas de barro, a menos que sejam arquitetados corretamente. A separação de preocupações se torna primordial. Veja winformsmvp.codeplex.com
Robert Harvey
1
Não há realmente um processo. O design é principalmente sobre como organizar, que vem com a experiência. Os princípios do SOLID são um bom começo, mas não são suficientes, e as pessoas tendem a se perder no SOLID e esquecer por que os princípios existem.
Robert Harvey
1
Comece pouco. Requisitos são problemas. Um problema pode ser tão grande quanto "Queremos desenvolver o próximo site Stackexchange" ou tão pouco quanto "queremos que nosso próximo Stackexchange tenha um login". Transforme um grande problema em muitos, mas menores. No geral, dê a si mesmo a chance de fazer as coisas "erradas" primeiro e melhorar com o tempo.
Laiv
1
I simultaneamente quer upvote e VTC isso ...
svidgen

Respostas:

21

Então, como posso aprender a realmente fazer design orientado a objetos? O que eu quero aprender é: dado que os requisitos sabem como começar a trabalhar neles em um processo que leva a descobrir o que precisa ser feito e aonde cada parte do código pertence. Como também posso aprender a julgar se minha ideia está correta ou não?

Bem, primeiro de tudo, pare de pensar no design orientado a objetos como correto. É como pensar no inglês como correto.

O paradigma orientado a objetos não está correto. Tem certas vantagens e desvantagens. É um ideal. Não é o nosso único. É melhor que nada, mas certamente não é tudo.

Eu tenho codificado por décadas agora. Eu estudei essas coisas por quase tanto tempo quanto as idéias existiram. Eu ainda estou aprendendo o que isso significa. Os especialistas ainda estão aprendendo o que isso significa. Todo o nosso campo tem menos de 100 anos.

Então, quando você pega uma pilha de requisitos e cria um código que os satisfaz, mas parece que o código que você escreveu é uma bagunça trágica, você não está sozinho. Código de trabalho é simplesmente o primeiro passo para obter um ótimo código. Código que não só funciona, mas que outros podem ler e entender facilmente. Código que pode ser adaptado rapidamente quando os requisitos mudam. Código que faz você querer sentar e dizer "Uau, isso é tão simples".

O problema é que não estamos sendo pagos para fazer tudo isso. Fazemos tudo isso porque somos profissionais. Temos que fazer tudo isso quando o chefe não está olhando, porque sempre há um prazo. Mas queremos voltar daqui a 5 anos e dizer aos novatos: "Ah, sim, eu escrevi isso. Ainda funciona né? Legal."

Como se chega lá? Prática. Não aceite QUALQUER idéia de design com fé. Alguém não cala a boca sobre como o design orientado a eventos simplifica esse design? Não tem certeza se eles estão certos? Crie seu próprio projeto de brinquedo em casa que use o padrão de observador. Mexa com isso. Tente encontrar coisas com as quais não ajuda.

Ler. Questão. Teste. Repetir.

Quando você chegar ao ponto de fazer isso por 80% da sua vida, ficará tão confuso quanto eu.

Confesso que, quando recebo os requisitos na maioria das vezes, penso "como isso pode ser feito?" - Eu não tenho idéia de como começar a trabalhar nos requisitos para descobrir o que deve ser feito. Minhas principais confusões, acredito, são o que devo codificar, que classes, interfaces e para onde vai cada parte da lógica, em qual classe cada coisa deve estar. O problema é que não sei por onde começar.

Eu costumava me sentir da mesma maneira. Então eu descobri a alegria de refatorar. Esteja disposto a adaptar os designs à medida que codifica. Tentar resolver tudo no papel antes do tempo é a maneira mais difícil de fazê-lo. Escreva um código que possa ser provado errado, prove errado e corrija-o.

candied_orange
fonte
2
Esta é uma ótima resposta. Venho programando há 15 anos e acrescentarei que todo o campo da Engenharia de Software (minha profissão) é "confuso" - é uma mistura de arte e função, e, dependendo do desenvolvedor, é mais um que o outro. Posso ter uma ideia para uma arquitetura no papel, mas nunca consigo descobrir os detalhes do design do OO até entrar na sujeira, mexer e descobrir o que funciona e o que não funciona.
Jropella #
Obrigado pela resposta! Portanto, o que você quer dizer é: quando temos pelo menos uma solução para implementar um requisito, e ele funciona, nós o implementamos; depois, como vemos como ele se relaciona com o outro código e outros requisitos, nós o refatoramos para torná-lo melhor? Mas ainda existem situações em que obtenho alguns requisitos e não tenho idéia de como começar. Nesses casos, você tem algum conselho sobre como começar? Às vezes, acredito que o melhor seria discutir os requisitos e as possíveis implementações, mas trabalho sozinho. Existe algum fórum em que esse tipo de discussão seja bem-vindo?
User1620696
2
Bem, primeiro, pare de trabalhar sozinho. Mesmo ter um novato sem noção que o atrasa para explicar as coisas é melhor do que isso. Segundo, aprenda a dividir um requisito em partes. Continue fazendo isso até ter algo gerenciável no qual possa obter tração. Escreva o código de prova de conceito em um ambiente completamente diferente, se necessário. Basta fazer algo que expresse sua compreensão do que é necessário. Então teste essa expressão. Você, meu achado, fez suposições ruins. Isso é bom. Esteja disposto a mudá-los.
Candied_orange 8/17
1

O desenvolvimento de software se resume à entrega do software em funcionamento, dentro do prazo e do orçamento, atendendo a todos os seus critérios de aceitação. Supondo que você tenha conseguido fazer isso, a qualidade percebida do código ou de sua estrutura é uma preocupação secundária.

O problema, é claro, é que escrever um novo código greenfield tende a ser muito mais barato e mais fácil do que manter o código legado; portanto, em vez de ficar muito preocupado com a qualidade ou a arquitetura do código, lembre-se de que seu problema real é a manutenção.

Normalmente, o código é considerado sustentável quando os custos, tempo e riscos associados à alteração desse código são proporcionalmente baixos o suficiente para que a correção de bugs ou a implementação de alterações nos requisitos ainda sejam econômicas e, ao implementar essas alterações, você não está perpetuando uma "espiral da morte" "da entropia de código.

Por outro lado, o código é considerado insustentável quando você não pode alterar ou refatorar com confiança, sem um sério risco de quebrar algo ou gastar tempo / dinheiro excessivo para garantir que nada seja quebrado - ou seja, quando o tempo, custo e risco envolvidos no trabalho com esse código são desproporcionalmente alto em comparação com os benefícios de fazer alterações (ou seja, seu empregador ou cliente não está perdendo dinheiro adicionando novos recursos, corrigindo bugs, etc.)

Lembre-se de que mesmo a bagunça de espaguete mais diabólica pode ser potencialmente mantida se você tiver provisões suficientes ao redor da bagunça para se proteger contra mudanças de quebra (embora esses casos sejam raros). O problema com uma bagunça de espaguete é que protegê-la contra mudanças quebradas tende a ser bastante cara e ineficiente - especialmente se você estiver fazendo isso retrospectivamente.

Talvez a maneira mais confiável de garantir que você tenha escrito código de manutenção seja escrever (sempre que possível) um conjunto adequado de testes automatizados ao mesmo tempo (além de aproveitar ao máximo todas as outras ferramentas de análise estática disponíveis).

Você não precisa seguir particularmente uma metodologia de desenvolvimento rigorosa, como TDD / BDD, para terminar com testes automatizados suficientes para permitir refatoração; você só precisa o suficiente para proteger o código contra alterações significativas acidentais no futuro.

Se seu código é coberto por testes automatizados, você pode relaxar sobre o design e a estrutura sabendo que está coberto por esses testes; você pode refatorar agressivamente posteriormente ou até jogá-lo fora e começar de novo.

Isso levanta a questão de como escrever código facilmente testável; esse é geralmente o principal argumento para seguir os princípios do SOLID; de fato, a marca registrada do código que segue os princípios do SOLID é que é fácil e economiza tempo / tempo escrever testes de unidade.

Obviamente, às vezes você também não tem tempo para escrever testes de unidade; no entanto, se você escreveu todo o seu código, tendo em mente a pergunta "Como escrevo testes automatizados para isso?" (mesmo que você não tenha implementado esses testes), provavelmente também conseguiu encontrar um design que seja razoavelmente sustentável.

Ben Cottrell
fonte
1
nunca temos tempo para escrever testes automatizados mas sempre temos tempo de testes manuais executar uma e outra vez ...
Nick Keighley
Da mesma forma, nunca temos tempo para escrever o código "corretamente" e "corretamente" na primeira vez, mas parece que temos um tempo sem fim para voltar e corrigi-lo, repetidamente, repetidamente, devido à mentalidade equivocada, mas tão predominante, apresentada em esta postagem.
Dunk
@ Dunk Eu não acho que é realista esperar que o código nunca mude ou seja revisitado. As práticas de teste de unidade e as diretrizes do SOLID são sobre incentivar práticas que resultam em códigos fáceis e baratos de mudar quando o inevitável acontece - por exemplo, alguém encontra um bug realmente estranho e obscuro que o desenvolvedor não considerou na época ou o cliente vê o solução e altera os requisitos, ou mesmo o código original continha erros porque os desenvolvedores são apenas humanos; ou talvez o desenvolvedor tenha entendido mal os requisitos ou tenha descoberto limitações técnicas anteriormente desconhecidas ...
Ben Cottrell
1
@BenCottrell - concordo totalmente. O código sempre precisará ser revisado. No entanto, por isso, leva as pessoas a dedicar algum tempo a fazer "design inicial" e a escrever um pouco de "código limpo" como algum tipo de falha. Eles usam o mantra "pontual" e "dentro do orçamento" para justificar código / design deficientes. Você pode usar todas as "práticas" que deseja, mas isso não comprará "códigos fáceis e baratos de alterar" sem ter um bom design e um "código limpo" relativamente para começar. Um bom design e um "código limpo" terão como subproduto o alcance real da meta dentro do prazo e do orçamento.
Dunk
@ Dunk Parece que você está dizendo que muitos desenvolvedores simplesmente não se importam com a qualidade do código, o que não acredito que seja o caso. Na realidade, acho que existem dois problemas maiores - primeiro, embora os desenvolvedores possam fornecer uma estimativa do orçamento e do prazo, as estimativas podem facilmente se mostrar erradas. Em segundo lugar, as partes interessadas no projeto recebem a última palavra em tempo / custo, o que significa que riscos, orçamentos e prazos substituem as preocupações técnicas. Dada a escolha entre "definitivamente atrasado / acima do orçamento" ou "código potencialmente ruim", acho que as partes interessadas frequentemente escolhem o último.
Ben Cottrell