O que é um processo simples para projetar um sistema OOP antes de codificá-lo?

10

Sempre que me pediam para construir um projeto, sempre consegui construí-lo, não antes de planejar um plano ou design, mas depois de escrever uma classe necessária, aprofundando todo o projeto, construindo de baixo para cima. Agora eu sei que essa não é a maneira correta de criar software, mas não é fácil para mim entender o que é chamado de Análise e Design Orientado a Objetos. Eu posso entender mais facilmente o design de procedimentos de cima para baixo, pois consiste apenas em dividir tarefas em subtarefas, coisas que têm sua contrapartida no código, funções. Mas a Análise e o Projeto Orientados a Objetos não consigo entender facilmente, pois não entendo como alguém pode saber de quais classes elas precisarão e como irão interagir, a menos que saibam como as codificarão.

Por uma vez que introduzimos o conceito de classes e objetos no processo de design, não podemos mais projetar de cima para baixo, porque não estamos mais dividindo nossos problemas naquelas coisas que podem ser implementadas como procedimentos. Em vez disso, de acordo com o que li sobre o assunto, precisamos determinar quais classes são necessárias e criar vários artefatos na Unified Modeling Language, que podemos usar quando implementamos o software. Mas esse tipo de processo de design eu não entendo. Pois como é possível saber de quais classes eles precisarão e como irão interagir, a menos que já tenham concebido todo o sistema?

Este é o meu problema. Eu não entendo como projetar um sistema orientado a objetos, embora compreenda os conceitos de programação orientada a objetos e possa usá-los em qualquer linguagem de programação orientada a objetos que eu conheça. Portanto, preciso que alguém me explique qual processo simples posso usar para projetar sistemas orientados a objetos de uma maneira que faça sentido para mim.

g.arbia777
fonte
8
"Agora eu sei que essa não é a maneira correta de criar software" - quem te contou isso? Parece que de alguma forma você cai na armadilha popular de acreditar que "o design é algo que você faz antes de codificar, talvez desenhando diagramas UML sofisticados". Para curá-lo desse equívoco, recomendo começar com "Code as Design", de Jack Reeves.
Doc Brown
@DocBrown. Você não acha que o design durante a codificação é o que torna nosso trabalho tão artesanal? Não consigo imaginar outras máquinas trabalhando da mesma forma. Imagine um arquiteto empilhando tijolos e argamassa e projetando o edifício / ponte no caminho.
LAIV
5
@Laiv: "codificação" faz parte do que em outras disciplinas de engenharia é chamado de design. Na construção de casas, a etapa do projeto até o produto final é feita com tijolos e argamassa de pilling. Na programação, essa etapa é realizada pelo compilador ao converter o design (= programa) no produto final (= binário executável). E essa não é uma nova sabedoria. Os ensaios de Reeves têm 25 anos.
Doc Brown
@DocBrown, o desenvolvedor. * Não tem mais curadoria? O botão de inscrição está quebrado, por exemplo.
Radarbob

Respostas:

20

Estilo cascata de cima para baixo OOAD não garante que o código que você escreve seja orientado a objetos. Vi montanhas de código estritamente produzido pela OOAD que o comprova. Se o OO estiver confundindo você, não procure aqui aqui. Você não o encontrará. OO NÃO exige que você projete de cima para baixo.

Se você gosta de codificar em uma aula, é assim que você gosta de codificar. Deixe-me contar uma dica. Procrastinar.

É incrível como é fácil projetar classes escrevendo código que as usa mesmo quando elas ainda não existem. Esqueça o procedimento. Esqueça a estrutura. Apenas obtenha um bom nível consistente de abstração e continue com ele. Não ceda à tentação e misture detalhes extras nela. Qualquer coisa que tire você da abstração atual pode ser executada em algum método que possa estar em outro objeto que de alguma forma saiba o que precisa saber. Não construa nada que você possa pedir para ser entregue a você.

Aprenda a escrever assim e você descobrirá que está fazendo OO sem se esforçar muito. Isso força você a olhar para seus objetos do ponto de vista de como eles são usados ​​(sua interface) e quais objetos sabem sobre quais outros objetos. Adivinhe quais são os dois principais pontos dos diagramas UML?

Se você pode entrar nesse modo de pensar, o que resta é a arquitetura. Ainda estamos todos descobrindo isso. Do MVC à arquitetura limpa, ao design orientado a domínio. Estude-os e brinque. Use o que funciona. Se você encontrar algo 100% confiável, volte e me avise. Faz isso há décadas e ainda estou procurando.

candied_orange
fonte
2
Ou você se vê sem fazer OO e, no entanto, tudo "de alguma forma" funciona bem de qualquer maneira ...
Derek Elkins saiu de SE
2
"É incrível como é fácil projetar classes escrevendo código que as usa mesmo quando elas ainda não existem" - chamo esse design de cima para baixo, mas parece que estou errado. O que é design de cima para baixo e como chamei isso? Está programando para uma interface?
Piovezan
Não é simplesmente de cima para baixo. Você também deve estar disposto a não criar coisas que pode pedir, aceitando parâmetros.
candied_orange
@Piovezan, você pode fazer isso mesmo quando a interface ainda não existe. Apenas ignore seu compilador um pouco. Mais tarde, você fará isso existir.
candied_orange
@CandiedOrange "Você também precisa estar disposto a não criar coisas que pode pedir, aceitando parâmetros." - Não sei se entendi. Você poderia esclarecer / fornecer um pequeno exemplo (ou contra-exemplo para esse assunto)?
Piovezan
4

Você afirma ser capaz de usar técnicas orientadas a objetos em seu código, de modo que já sabe como projetar um sistema orientado a objetos , acredito que seu problema é mais uma questão de quando , se você não pode ou não. Você parece confortável com o design orientado a objetos de uma maneira iterativa de curto prazo, em vez de um planejamento de longo prazo.

Ao desenvolver um projeto pela primeira vez, pode ser muito difícil planejar e projetar, é quando o desenvolvimento ágil é favorecido em relação ao desenvolvimento em cascata , pois o grande escopo de um plano em cascata geralmente não captura todas as complexidades de um projeto de software.

Você afirma que o desenvolvimento on-the-fly sem um "plano inicial" é:

"... não é a maneira correta de criar software ..."

Se o seu problema é que seu plano inicial não é detalhado o suficiente, dedique um pouco mais de tempo a explicar seus primeiros pensamentos. Qual é a primeira parte do programa que você planeja escrever? Do que vai precisar ? Talvez nem pense em quais objetos começar, em vez disso, pense em quais recursos e planos a partir daí.

Se o seu problema é que você não está confiante em suas habilidades de documentação / design / UML , pratique documentando um projeto existente.

Pessoalmente, eu recomendaria não se preocupar com seus projetos sendo perfeitamente orientados a objetos, a maioria dos sistemas não é 100% orientada a objetos. O objetivo é criar uma melhor compreensão e visualização do sistema, não uma abstração perfeita. A orientação a objetos não é a bala de prata, é apenas mais uma ferramenta no cinto.

Erdrik Ironrose
fonte
Eu também queria mencionar, embora um pouco fora de tópico para a resposta ... Seus planos não precisam ser muito grandes! Às vezes, um plano é apenas uma questão de "Eu quero executá-lo e ele faz uma coisa". Isso é bom o suficiente, se isso é realmente tudo o que vai fazer.
você precisa saber é o seguinte
2

OOAD é uma utopia. Com isso, não quero dizer que seja a melhor abordagem, quero dizer que nunca é realmente possível em minha humilde opinião. Na minha experiência, algo sempre muda, sejam requisitos ou especificidades, ou mesmo um conflito de dependência que o força a substituir completamente uma dependência. Seja porque aprendi dessa maneira ou porque é o que vem mais naturalmente para mim, minhas idéias para o design surgem mais rapidamente quando estou escrevendo código. Se eu estou prestes a codificar e não tenho uma idéia clara de como estruturarei o código, tentarei dedicar tempo para entender verdadeiramente o problema primeiro, embora, na maioria das vezes, veja o necessidade de uma aula e eu vou fazer isso.

Meu conselho seria que a melhor coisa que você pode fazer por si mesmo é codificar usando fachadas , fornecendo uma interface simples para entrada e saída, e espero que as entradas e saídas não mudem frequentemente. Embora, mesmo assim, saibam que não é um problema de design, mas sim um problema de especificações (alteração na necessidade / operação / funcionalidade). Isso tornará seu programa um tanto resistente a problemas que ressoam dentro dele para aqueles que chamam seu programa ou seção de código e vice-versa.

No que diz respeito ao design de um sistema orientado a objetos, algo deve ser dito para tentar tornar tudo orientado a objetos quando não deveria. Esse é um erro comum entre linguagens de programação OOP, como C # e Java, é tentar tratar tudo como um objeto, o que geralmente resulta na criação de uma única instância de uma classe para executar o que de outra forma seriam métodos estáticos que não mudam de estado. Dito isso, é claro que você deve usar o design de POO onde aplicável, embora não sinta que está fazendo algo errado quando parecer mais natural escrever um método estático. Nem sempre é o instinto errado.

Você deve usar uma classe quando responder sim a qualquer uma das seguintes perguntas:

  • Eu tenho um grupo de informações que pertencem ao mesmo conceito (ou seja, nome, sobrenome, endereço)?
  • Preciso executar uma operação que exija várias informações (ie calculatePrice(basePrice, quantity, tax))?
  • Eu tenho outro else se com grandes blocos de código executando operações ligeiramente diferentes com as mesmas informações ou informações semelhantes (ou seja, if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak())
  • Eu tenho uma classe existente que executa mais de uma tarefa específica e está crescendo um pouco demais?

Depois de um tempo, será uma segunda natureza criar classes. Não tenha medo de usá-los se o seu código estiver em um dos casos acima. Espero que ajude!

Neil
fonte
2

Eu acho que os comentários feitos por Doc Brown nos comentários merecem muito mais visibilidade do que um comentário, pois ele está absolutamente certo:

" Agora eu sei que essa não é a maneira correta de criar software " - quem te contou isso? Parece que de alguma forma você cai na armadilha popular de acreditar que "o design é algo que você faz antes de codificar, talvez desenhando diagramas UML sofisticados". Para curá-lo desse equívoco, recomendo começar com "Code as Design", de Jack Reeves. - Doc Brown 21 de junho às 5:27

@Laiv: "codificação" faz parte do que em outras disciplinas de engenharia é chamado design. Na construção de casas, a etapa do projeto até o produto final é feita com tijolos e argamassa de pilling. Na programação, essa etapa é realizada pelo compilador ao converter o design (= programa) no produto final (= binário executável). E essa não é uma nova sabedoria. Os ensaios de Reeves têm 25 anos. - Doc Brown 21 de junho às 6:39

Esse mesmo sentimento também é ecoado em outros lugares. Considere as palestras de Glenn Vanderburg sobre "Real Software Engineering" e, em certa medida, as palestras "Craft, Engineering e the Essence of Programming" e "Craft and Software Engineering". Considere também as páginas / discussões WhatIsSoftwareDesign e TheSourceCodeIsTheDesign no wiki C2.

O conceito do código como sendo o design não é específico para nenhum paradigma. Pode ser aplicado igualmente a orientação a objetos, funcional, processual, lógica ou qualquer outra coisa. A idéia subjacente é a mesma - o design é o próprio código-fonte. O ato de construção é o processo pelo qual o código fonte (o design) é transformado em algo utilizável por um intérprete ou compilador.

Em um sistema complexo, é provável que haja algum projeto de arquitetura de nível superior - identificando subsistemas, componentes, módulos, serviços e alocando requisitos a eles antes de começar a escrever o código. Você pode usar a UML como uma maneira de criar, documentar e auxiliar nas discussões sobre esse projeto de arquitetura. Considere a idéia de Modos UML que Martin Fowler discute , particularmente a UML como Sketch e a UML como Notes . Considere também algumas idéias dos modelos Agile Modeling - Modelagem de Arquitetura Inicial , Modelagem de Iteração e Just Barely Good Enough .

Tudo isso significa que a maneira correta de criar software não é desenvolver o projeto inteiro. É gastar apenas o tempo suficiente para entender os requisitos mais críticos (no momento atual), identificar dependências técnicas e compensações entre requisitos e depois tirar vantagem do fato de que o software é flexível. Reconheça também que o custo de projetar e produzir algo é incrivelmente baixo (especialmente se comparado a projetar e produzir algo em muitas outras disciplinas de engenharia). Portanto, itere suas atividades de design (codificação) e aproveite o quão fácil e barato é construir ou modificar progressivamente o que você fez.

Thomas Owens
fonte
1

OOAD é sobre identificar entidades e modelar objetos ou conceitos da vida real com um grau de abstração. Você perceberá que é mais fácil se, em vez de escrever classes, você escrever interfaces no início, já que você ainda não precisa implementá-las ainda, mas o código é compilado.

OOAD não exclui a possibilidade de pensar no sistema como grandes módulos. Você ainda pode fazer isso. Cada módulo existe para satisfazer um conjunto de histórias de usuários (casos de uso). Tais histórias de usuários precisam de classes que colaborem para cumpri-las.

Uma diferença importante entre as abordagens processuais de um OO é que geralmente o pensamento procedimental mapeia os requisitos para as telas, enquanto o OOD tem uma tendência a pensar no que acontece sob o capô, deixando o front-end feito por outra pessoa ou de maneira não OO.

Existe uma técnica na Extreme Programming chamada CRC Cards . CRC significa "classe-responsabilidades-colaboradores".

Basicamente, você identifica classes evidentes e atribui um cartão a cada uma. Digamos, a turma Invoicetem seu próprio cartão.

Para cada classe de portadores de cartão, escreva quais seriam as responsabilidades dessa classe, por exemplo "calcula um total geral" .

Também para todas as classes de portadores de cartão, você escreve o que outras turmas precisam pedir algo para cumprir suas próprias responsabilidades. Aqui você pode descobrir que Invoiceprecisa da colaboração InvoiceDetailou até mesmo descobrir que essa classe é necessária em primeiro lugar.

Você pode descobrir que algumas responsabilidades às quais pensava pertencer Invocerealmente pertencem a um de seus colaboradores.

Após o exercício, todo cartão se torna uma classe, toda responsabilidade se torna um método e todo relacionamento de colaboração pode se tornar uma composição, uma agregação ou uma mera ligação.

Esse exercício pode (e deve) ser feito em um grupo, onde até os empresários participam.

Você pode aprender mais sobre esta técnica nestes links:

http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

Exemplos de cartões CRC:

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Tulains Córdova
fonte
0

O principal desafio para nós, como uma comunidade de profissionais de software; mais especificamente, profissionais de design orientado a objetos, é o de materializar todos os nossos problemas / tarefas em uma parte de programação. Seja tarefas - representadas como funções ou atores das tarefas - representadas como interfaces / classes [dirigindo-se para o OOAD]. À medida que evoluímos nossos hábitos de criação de software, obtemos continuamente conhecimento sobre várias metodologias / estruturas. Nosso ponto de vista é cada vez mais refinado para segregar claramente os objetos e qual objeto executaria qual função.

Quanto à decomposição de seus problemas em subproblemas com a presença de objetos ao redor, você ainda pode fazer isso de maneira conveniente, pois VOCÊ tem o controle total de quais objetos deseja exibir. Você também tem a conveniência de transmitir natureza e propósito aos seus objetos e interfaces. Tudo o que você precisa fazer é visualizar a declaração do problema e pensar em qual finalidade / funcionalidade pode ser atribuída a qual objeto.

Tentarei explicar mais com a ajuda de um exemplo da gama de automóveis e destacarei duas maneiras diferentes de visualizar o mesmo modelo de objeto.

Tomemos um exemplo do fabricante de automóveis que abrange várias categorias de automóveis: veículos comerciais, carros de consumo (sedans, hatchback, station wagons) etc.

Para que o fabricante tenha claramente uma separação de categoria e finalidade, existem várias maneiras pelas quais ele pode criar essas classes.

Fabricante de veículo OOAD

  1. Com base na categoria (setor de mercado) do veículo: veículo pesado, veículo de consumo [sedan, hatchback, perua etc.]

  2. Com base na capacidade do motor e na maneira de dirigir: 800-1500 CC,> 1500 CC etc.

Seguindo a melhor maneira pela qual o fabricante pode atribuir funções individualmente a objetos pertencentes a cada uma dessas classificações, ele pode escolher um design de objeto subjacente apropriado e criar um modelo sobre ele.

Akash Mishra
fonte
Você começa bem, mas o último pouco se parece com a falácia de que o OOD é sobre categorizar as coisas em vez de agrupar comportamentos semelhantes.
Pete Kirkham