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.
fonte
Respostas:
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.
fonte
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" é:
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.
fonte
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:
calculatePrice(basePrice, quantity, tax)
)?if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }
==>animal.speak()
)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!
fonte
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:
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.
fonte
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
Invoice
tem 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
Invoice
precisa da colaboraçãoInvoiceDetail
ou até mesmo descobrir que essa classe é necessária em primeiro lugar.Você pode descobrir que algumas responsabilidades às quais pensava pertencer
Invoce
realmente 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:
fonte
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.
Com base na categoria (setor de mercado) do veículo: veículo pesado, veículo de consumo [sedan, hatchback, perua etc.]
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.
fonte