Por favor, explique por que precisamos de SRP em "Inglês Simples" apesar de suas desvantagens?

4

Você pode explicar em inglês simples por que precisamos do Princípio da Responsabilidade Única ?

Especialmente que move o que chamo de "inchaço" para outros lugares. Veja abaixo para mais informações. Por inchaço quero dizer, no meu caso específico, eu tenho várias responsabilidades em um controlador que se exibem como funções / métodos. Aplicando o SRP da maneira que entendi, divide o Controlador em vários Controladores, cada um com um método. O "inchaço" é, portanto, movido de "número de métodos" para "número de arquivos".

O artigo no link do wiki acima explica o que é o SRP, mas não parece me dizer "por que" nós o usamos. Eu gostaria de uma razão / explicação / técnica não tão técnica (ou talvez até técnica) para por que precisamos desse princípio.

Porque, na minha experiência atual, a implementação do SRP leva a código menor e mais estreitamente alinhado, mas cria mais arquivos.

Exemplo

Eu tenho um arquivo de controlador que pode ter várias ações / métodos dentro dele. Para manter todas essas ações no controlador, tenho que inflar o número de dependências que tenho que passar para o controlador, porque as dependências devem cobrir todas as ações possíveis, mesmo que qualquer ação específica não precise de todas das dependências.

para que eu possa dividir o controlador em 2 ou mais partes para onde eu tenho uma ação por controlador. Isso satisfaz o SRP, mas inflige o número de arquivos que eu tenho que criar.

Exemplo

/*
 * Repository initialized with $quoteId
 */
class Repository
{
    private $quoteId;

    function __construct($quoteId)
    {
        $this->quoteId = $quoteId;
    }        
}

/*
 * Controller initialized with $repository
 */   
class Controller
{

    private $repository;

    function __construct($repository)
    {
        $this->repository = $repository;
    }        

    function addForm()
    {
         //repository is initialized elsewhere with $quoteId
         $this->repository->getFormDataFromQuote();
    };

    function viewForm()
    {
         $id = int_val($_GET['id']);

         //does *not* use $quoteID
         $this->repository->getViewDataFromId($id);
    };
}

SRP

Para manter o SRP, podemos dividir o Controller em dois, um para addForm, um para viewForm. Podemos então dividir o Repositório em dois também, um para cada método no Controller. Assim, começamos com 2 arquivos, e terminaremos com 4 arquivos.

Desvantagens

Eu interpreto o SRP aqui como "Divida o controlador" (e presumo que quaisquer outros arquivos de suporte também, como o Repositório aqui) em dois neste caso. Assim, no exemplo acima, haverá ControllerAddForm e ControllerViewForm , e se eu estiver usando um repositório para esses métodos, que eu sou, eu tenho que criar RepositoryViewForm e RepositoryAddForm para satisfazer o SRP também, porque diferentes métodos de repositório são necessários para as diferentes ações do Controlador. Assim, recebo 2x arquivo inchado. Por que novamente o SRP é recomendado apesar de mover o inchaço para o número de arquivos em vez de para o número de métodos por arquivo.

    
por Dennis 07.11.2017 / 22:43
fonte

4 respostas

12

Você precisa do SRP pelas mesmas razões pelas quais não deixa o seu Sous Chef consertar seu carro. Eles têm responsabilidades diferentes.

Cada pessoa é especializada em uma área diferente de especialização. Se isso ajudar, pense em suas aulas como funcionários. Dê a cada um um título de trabalho; geralmente é o nome de cada classe. Desenvolva a "área de especialização" dessa classe e, em seguida, escreva o código que preenche essa área de especialização.

    
por 07.11.2017 / 23:13
fonte
12

O SRP é um dos princípios de engenharia de software mais incompreendidos. Não há nem mesmo uma definição precisa do que é uma "responsabilidade", tornando isso mais difícil de entender.

Grosso modo, uma "responsabilidade" não é uma única ação atômica, mas sim um conjunto de ações que estão intimamente relacionadas. Adicionar um formulário, visualizar um formulário, enviar um formulário etc. tem a mesma responsabilidade de "gerenciar o formulário X".

To abide SRP we can break up Controller into two, one for addForm, one for viewForm.

Não. Para cumprir o SRP, você tem controladores separados para gerenciar cotações e gerenciar clientes. Eles podem delegar a modelos que gerenciam a persistência para cada tipo de dados (cotações e clientes).

Em geral, refatorar grandes unidades de código em unidades menores de código é uma boa ideia até o ponto em que há muitas pequenas unidades de código para raciocinar. Pessoalmente, acho que manter Todos os meus "gerenciar formulário de cotação" código em uma classe é uma ótima idéia: eu sei exatamente onde procurar código do controlador para citações. Eu sei que todo o código está lá para esse propósito, mas nenhum código para gerenciar clientes.

Observe também que o SRP, como se aplica a um sistema de gerenciamento de cotações baseado na web, será diferente do que com o kernel do Linux. Dê um passo para trás e observe o design geral e tente encontrar as divisões naturais em relação ao que o código está fazendo. Em seguida, pergunte a um dos seus colegas .

    
por 07.11.2017 / 23:14
fonte
3

O SRP é perigoso (assim como a maioria dos princípios de design) se você o seguir como dogma. Minha perspectiva é respeitar o SOLID, mas cuidado com seu strong culto (ure), especialmente quando alguém está derramando mais calor do que luz citando esses princípios.

Quando leio sua pergunta, penso que o SRP está em oposição a YAGNI .

Usando seu exemplo de controlador, faz pouco sentido separar seu controlador em classes distintas se os requisitos nunca mudarem; você não estará mantendo o projeto após uma demonstração do "Shark tank", e / ou você nunca precisará reutilizar parte da lógica do seu controlador em outro projeto. Eles são todos grandes, talvez.

Robert Martin dá um exemplo detalhado usando o código em um projeto de boliche. O design leva a uma classe Game que tem duas responsabilidades: controlar os quadros e calcular a pontuação.

No experimento de programação de programação em pares em seu livro, um dos desenvolvedores acabou sugerindo refatorar essas responsabilidades separadas em classes distintas, Game e Scorer , citando o SRP como a motivação. Um comentário sarcástico é feito de que os programadores do Linux gostam de fazer tudo em uma única função ilegível ...

É um bom exemplo do Ying e Yang do SRP. Ter módulos separados para as responsabilidades de Jogo e Pontuação tem a vantagem de permitir que os dois evoluam de forma mais independente, talvez até mesmo permitindo que um novo programador encontre onde no código esse erro complicado poderia ser (há menos linhas em Scorer do que se todo o código fosse combinado em um módulo), etc. Essas classes poderiam teoricamente ser reutilizadas em outros aplicativos que precisam de seus serviços ( Jarts alguém?).

Mas há um lado negativo: antecipar mudanças que nunca ocorrerão é um desperdício de esforço. Que mudanças poderiam possivelmente chegar às regras do jogo de boliche! Teoricamente eles existem (ei, poderia haver uma ordem executiva de 45?) E se eles acontecessem, ter módulos separados certamente seria melhor então, certo?

Ah, YAGNI diz que não desperdice sua energia em mudanças até que elas cheguem. É engenharia excessiva.

Finalmente, o SRP (e o design orientado para a responsabilidade em geral) é uma heurística (o que parece ter funcionado no passado, mas não há garantia de que, aplicando-o, você se beneficiará). Ninguém fez pesquisas suficientes para lhe dizer quando vale a pena. Os problemas de design são difíceis e tentar usar um "princípio" dogmaticamente levará à decepção.

Eu achei o Wiki Princípios realmente interessante (embora incompleto) porque ele tenta mapear as relações entre esses vários princípios de design. Para o SRP, há muitos princípios relacionados, por exemplo, separação de interesses, lei de Curly, etc. . Lendo aqueles também ajudará você a entender os trade-offs.

    
por 10.11.2017 / 22:43
fonte
1

O Princípio de Responsabilidade Única (SRP)

As turmas não devem ter mais de um foco de responsabilidade. O contexto empresarial também impulsionará o nível de segregação de responsabilidade em uma classe.

Nota:

  • As classes podem estar razoavelmente envolvidas em diferentes interações, é o foco que é o problema.
  • Este princípio é quase idêntico ao princípio da coesão

Análise de SRP: Por exemplo, observe cada método, x, na classe, diga Car e pergunte: " Car tem a responsabilidade principal de x-ing?" Se a resposta for não, o método não pode pertencer lá. Pergunte em relação ao object , não ao action .

    
por 07.11.2017 / 23:29
fonte