Ao escrever código orientado a objeto, eu deveria estar sempre seguindo um padrão de design?

37

Existe um padrão de design concebível para qualquer programa orientado a objetos? Pergunto isso porque recentemente vi uma implementação de uma classe Door com um Lock . Fazia parte de um teste e a resposta dizia que o código segue o padrão de Objeto Nulo:

class Lock
{
public:
    virtual void close() = 0;
    virtual void open() = 0;
    virtual bool is_open() const = 0;
    virtual ~Lock() { }
};

class DummyLock
    : public Lock
{
private:
    DummyLock();
    DummyLock(const DummyLock&) = delete;
    DummyLock& operator=(const DummyLock&) = delete;

private:
    void close() { }
    void open() { }
    bool is_open() const { return true; }

public:
    static DummyLock m_instance;
};

class Door
{
public:
    Door() : m_lock(DummyLock::m_instance) { }
    Door(Lock &lock) : m_lock(lock) { }

public:
    Lock& get_lock() const { return m_lock; }

private:
    Lock &m_lock;
};

Isso me fez pensar: Este código segue um bom padrão de design, embora a descrição seja tão simples (essa classe está projetando uma classe de porta com um cadeado), então se eu estiver escrevendo um código mais complexo, sempre algum padrão de design que estou seguindo?

    
por user2030677 02.10.2014 / 19:56
fonte

9 respostas

143

should there always be some design pattern that I am following?

Querido Deus NÃO!

Quero dizer, você pode ir em frente e dizer que qualquer código aleatório está seguindo algum padrão XYZ aleatório, mas isso não é mais útil do que eu alegar ser o rei da cadeira do meu computador. Ninguém mais sabe realmente o que significa e mesmo aqueles que não respeitarão exatamente o meu pedido.

Padrões de design são uma ferramenta de comunicação para que os programadores possam dizer a outros programadores o que foi feito ou o que deve ser feito sem gastar muito tempo se repetindo. E como são coisas que surgem várias vezes, são conceitos úteis para programadores aprenderem "hey, fazer o XYZ sempre parecer porque é bom / útil".

Eles não substituem a necessidade de você pensar por si mesmo, adaptar os padrões para o problema único à sua frente ou lidar com todo o inevitável coisas que não se encaixam em bons baldes.

    
por 02.10.2014 / 20:04
fonte
37

Não.

Isso é o que a Gang of Four (que originalmente popularizou os padrões de design) teve a dizer sobre isso em seu livro :

"No discussion of how to use design patterns would be complete without a few words on how not to use them. Design patterns should not be applied indiscriminately. Often they achieve flexibility and variability by introducing additional levels of indirection, and that can complicate a design and/or cost you some performance. A design pattern should only be applied when the flexibility it affords is actually needed."

O exemplo que você mostra não faz muita coisa (acho que não foi feito, acho que foi apenas um exemplo). Por si só, não precisa do padrão de objeto nulo. No contexto de um programa maior, isso pode acontecer.

A abordagem errada está assumindo que só porque foi rotulado como um "padrão de design" deve ser bom, e então procurar por mais lugares para encaixar mais padrões. Use-os quando eles se encaixam no programa e realmente resolvem um problema para eles. você.

    
por 02.10.2014 / 23:11
fonte
29

if I am writing more complex code, should there always be some design pattern that I am following?

Não. Padrões de design são apenas isso: padrões em relacionamentos entre objetos. Em outras palavras, relacionamentos que são usados e reutilizados com frequência suficiente para que alguém diga "Ei, parece que estamos fazendo muito isso, vamos dar um nome a ele". A lista de padrões de design não foi determinada de uma só vez no início da OOP e depois transmitida pelo GOF ! Eles foram descobertos e eventualmente documentados e depois popularizados pelo livro.

Dito isso, uma grande parte do benefício dos padrões de design é que eles tornam mais fácil pensar em design de software em um nível mais alto. Eles permitem que você não se preocupe com os detalhes da implementação e pense mais sobre o quadro geral. Nesse sentido, eles libertam você da minúcia, mas eles também podem limitá-lo da mesma maneira que o modo como você se expressa pode ser limitado pelas palavras que você conhece. Assim, pode chegar um momento em que é um padrão de design para a maioria do que você faz, simplesmente porque os padrões que você conhece são os termos em que você pensa. Mantenha os olhos abertos para os casos em que você pode estar abusando de um padrão, e onde você pode precisar pensar mais profundamente sobre as melhores maneiras de fazer as coisas.

Além disso, perceba que, na prática, muitas vezes você não implementa um determinado padrão de design, mas reconhece o padrão em algum código existente, como uma estrutura de objeto. Saber sobre padrões de design comuns torna muito mais fácil aprender como um framework é destinado a ser usado, porque você pode ver as relações entre classes em termos que você já entende.

    
por 02.10.2014 / 20:12
fonte
10

Padrões de design têm duas vantagens

  1. Eles são fáceis de descrever para outros desenvolvedores, porque as pessoas geralmente concordam sobre quais padrões são
  2. Eles tendem a ser espancados de forma bastante ponderada por nossos predecessores, de modo que seus pontos strongs e fracos são bem compreendidos.

Os objetivos de cada programa devem ser

  1. Funciona. Ele tem que fazer o que for o objetivo final, ou não importa quantos padrões de design você usa. Os padrões de design OO facilitam a definição do problema em bits fáceis de entender, por isso é mais fácil provar que funciona.
  2. É fácil de ler. É aqui que os padrões de design são bons. Os problemas OO que eles resolvem são complicados. Se você resolvê-los de maneira "padrão", fica mais fácil para o próximo desenvolvedor
  3. É fácil crescer. Quase 0 programas modernos terminam onde todos planejaram. Todo programa cresce após o lançamento inicial. Os padrões OO são conhecidos por serem curiosamente bons em crescimento.

Dito isso, todas as referências a padrões de design OO são "elas são boas no trabalho". Eles não são perfeitos, mas preenchem um nicho de forma muito eficaz. Use-os quando eles trabalharem, evite-os quando eles não funcionarem.

Como exemplo, de "código complexo", como você mencionou na sua pergunta, use uma linguagem de script que escrevi. A maior parte é OO com padrões de design em todos os lugares. No entanto, quando chegou a hora de escrever o coletor de lixo, eu abandonei sem cerimônias todas as pretensões de OO, porque as coisas específicas que eu precisava fazer eram mais bem modeladas como um bom e velho ataque de bits. Não há um padrão OO na coisa toda até chegar a escrever finalizadores, onde mais uma vez OO começou a ser um modelo útil novamente. Sem pompa nem circunstância, o código repentinamente voltou a usar técnicas OO novamente.

Use padrões de design sempre que eles melhorarem o seu produto; evite-os quando eles piorarem seu produto.

    
por 02.10.2014 / 23:02
fonte
5

Eu vou diminuir a tendência um pouco, porque a resposta é mais sutil do que outras respostas estão deixando transparecer. Cada classe que você escreve não deve empregar um padrão de design, mas a maioria dos programas não-triviais que você escreve provavelmente deve.

Um programa não trivial sem nenhum padrão de design indica:

  • Seu programa é tão único que nenhuma parte dele é semelhante a problemas comuns que os programadores enfrentaram antes. Ou
  • Seu programa contém esses problemas comuns, mas você os resolveu de uma maneira melhor que ninguém pensou antes.

Ambos os cenários são altamente improváveis, sem ofensa.

Isso não significa que o padrão de design deva direcionar seu design, ou que você deve inserir um indiscriminadamente, porque você acha que ficará ruim se você não o fizer. O padrão de design errado é pior do que nenhum.

O que isso significa é que você deve olhar para a falta de padrões de projeto em seu programa como um cheiro de código. Algo que faz você dar uma segunda olhada e reavaliar se o seu design não poderia ser mais limpo. Se, nesse ponto, você decidir deixar os padrões de projeto fora de um programa, isso deve ser uma decisão deliberada e informada, e não por acaso.

Por exemplo, você não diz: "Preciso modelar uma porta e um cadeado, que padrão de design devo usar?" No entanto, se você projetou primeiro sem usar nenhum padrão de design, isso deve levá-lo a dizer algo como: "Tenho um monte de verificações de nulo neste código, imagino se há um padrão de design que possa ajudar a gerenciá-los".

Veja a diferença? É uma distinção sutil mas importante.

    
por 03.10.2014 / 19:21
fonte
4

Questão quebrada. Deixe-me dar a você uma nova definição de padrão de design que desfazia muitos danos liberados pelo GoF: um padrão de design é uma boa prática de codificação . É isso.

Qualquer módulo razoavelmente complexo terá vários padrões de projeto. Toda vez que você faz cache, é provavelmente um padrão flyweight, mas eu não vou revogar seu grau de programação se você não chamar assim. Toda vez que você tem um retorno de chamada, você está em algum tipo de padrão de evento / incêndio / retorno de chamada. etc Se você tem a palavra "estática" você tem um singleton. Se você tem um construtor estático, você tem um padrão de fábrica. Se um recurso for passado para o seu módulo, você está usando a injeção de dependência.

"Design pattern" é um termo quebrado pouco popularizado pelo GoF, que faz parecer que todos os padrões estão no mesmo nível ou que você deve usar o médico recomendado de 3 a 5 por aula. Toda vez que você faz algo certo que alguém fez certo, é um padrão de design . Um for(;;) é um padrão comum usado para representar um loop infinito, por exemplo.

Você não deve tentar aprender vários padrões de design. O conhecimento de programação não é indexado por padrões de projeto! Em vez disso você deve aprender a escrever um bom código lendo livros, blogs e participando de conferências em seu campo. Por exemplo, se você já usa a injeção de dependência, mas não a rotulou, pode se beneficiar de sempre usando DI ou usando uma estrutura IoC. Ou, se você estiver com dificuldades para codificar diretamente em eventos e retornos de chamada, vá aprender o Haskell para conhecer os padrões de design funcional e isso se torna fácil.

E se toda a sua turma é uma grande coisa que alguém fez certo, por que você está reinventando a roda? Apenas use o material deles.

    
por 03.10.2014 / 03:35
fonte
0

Você deve sempre seguir os princípios de design OO (por exemplo, modularidade, ocultação de informações, alta coesão, etc.). Padrões de design são um nicho relativamente refinado dos princípios de design OO, especialmente se você considerar o princípio KISS .

Padrões são soluções para problemas comuns de projeto. Esses problemas vêm de um dos dois locais (ou uma mistura de ambos): o espaço do problema (por exemplo, software para gerenciar Recursos Humanos em uma empresa) e o espaço da solução . Um programa OO é uma instância dentro do espaço da solução (por exemplo, uma das várias maneiras de projetar um programa OO para facilitar o gerenciamento de RH).

Não é tão fácil saber quando usar um padrão. Alguns padrões são de baixo nível, mais próximos da codificação e do espaço da solução (por exemplo, Singleton, Objeto Nulo, Iterador). Outros são motivados por requisitos no espaço do problema (por exemplo, padrão de comando para oferecer suporte a desfazer / refazer, estratégia para oferecer suporte a vários tipos de arquivo de entrada / saída).

Muitos padrões vêm da necessidade de suportar variações do software no futuro. Se você nunca precisa fazer essas variações, um padrão pode ser um design excessivo. Um exemplo seria usar o padrão do adaptador para trabalhar com o banco de dados de RH externo existente. Você decide aplicar o Adapter porque o banco de dados atual funciona com o Oracle e talvez você queira oferecer suporte ao NoSQL no futuro. Se o NoSQL nunca chegar à sua organização, esse código do Adaptador poderá ser inútil. Veja YAGNI . Suporte para variações que nunca ocorrem é o uso incorreto de um padrão de design.

    
por 05.10.2014 / 15:55
fonte
0

Padrões são soluções comuns para problemas comuns. Estamos sempre seguindo alguns padrões, os padrões por GoF abordam os mais recorrentes. Isso, para ter um entendimento compartilhado e uma abordagem compartilhada conhecida pelos engenheiros de software.

Dito isso, minha resposta é não, mas sim, você está sempre seguindo um padrão próprio. Como o GoF corretamente coloca -

One person's Pattern is another person's primitive building block.

Grande citação.

    
por 17.11.2014 / 05:39
fonte
0

Quando escrevo código, não planejo usar deliberadamente tantos padrões de design quanto possível. Mas, suponho, subconscientemente, quando obtenho um problema de codificação, um dos padrões de design parece se encaixar, e eu apenas o uso. E às vezes nada se encaixa. O que é mais importante para mim é escrever código que faça o trabalho e seja fácil de manter e crescer.

Aqui está um artigo sobre como aplicar os princípios do OOD usando padrões de design e exemplos de código também (em C ++). Ele mostra como e quando aplicar alguns dos padrões de design para escrever código limpo.

    
por 12.01.2015 / 17:10
fonte