Implementação do Princípio da Responsabilidade Única

5

No meu tempo livre, projetei um CMS para aprender mais sobre design e arquitetura de software, etc.

Passando pelos princípios do SOLID, eu já notei que idéias como "MVC", "DRY" e "KISS", praticamente se encaixam. Dito isso, ainda estou tendo problemas para decidir se uma das duas implementações é a melhor escolha quando se trata do Princípio da Responsabilidade Única.

Implementação # 1:

class User
    getName
    getPassword
    getEmail
    // etc...

class UserManager
    create
    read
    update
    delete

class Session
    start
    stop

class Login
    main

class Logout
    main

class Register
    main

A ideia por trás dessa implementação é que todas as ações baseadas no usuário são separadas em classes diferentes (criando um possível caso do apropriadamente chamado Código Ravioli ), mas seguindo o SRP para um" tee ", quase literalmente.

Mas depois pensei que era um pouco demais e criei a próxima implementação

class UserView extends View
    getLogin //Returns the html for the login screen
    getShortLogin //Returns the html for an inline login bar
    getLogout //Returns the html for a logout button
    getRegister //Returns the html for a register page
    // etc... as needed

class UserModel extends DataModel implements IDataModel
    // Implements no new methods yet, outside of the interface methods
    // Haven't figured out anything special to go here at the moment
    // All CRUD operations are handled by DataModel 
    //   through methods implemented by the interface

class UserControl extends Control implements IControl
    login
    logout
    register
    startSession
    stopSession

class User extends DataObject
    getName
    getPassword
    getEmail
    // etc...

Isso obviamente ainda é muito organizado, e ainda é muito "responsabilidade única". A classe User é um objeto de dados no qual eu posso manipular dados e, em seguida, passar para o UserModel para salvá-lo no banco de dados. Toda a renderização de dados do usuário (o que o usuário verá) é manipulada por UserView e seus métodos, e todas as ações do usuário estão em um espaço em UserControl (mais algumas coisas automatizadas exigidas pelo CMS para manter um usuário logado ou para garantir que eles fiquem de fora.) Eu pessoalmente não consigo pensar em nada de errado com essa implementação também.

Em meus sentimentos pessoais, sinto que ambos estão efetivamente corretos, mas não consigo decidir qual deles seria mais fácil de manter e estender à medida que a vida continua (apesar de inclinar-se para a Implementação nº 1.)

Então, e vocês? Quais são suas opiniões sobre isso? Qual é o melhor? Quais princípios (ou nuances) desse princípio eu perdi em qualquer projeto?

    
por Mike S 10.11.2011 / 03:46
fonte

3 respostas

5

Eu sempre considerei o princípio da responsabilidade única mais uma filosofia do que um princípio.

Robert C. Martin (Tio Bob) reafirma o Princípio da Responsabilidade Única (vinculado ao PDF) :

There should never be more than one reason for a class to change

Citado na resposta que você recebeu sua postagem.

Quando tentamos apaziguar a SPR, nos concentramos na implementação e não na finalidade.

Erro principal.

Meu entendimento do SRP é este, quando uma adição borrar a responsabilidade de uma implementação, o ponto focal deve ser reconsiderado.

Para mim, é tudo sobre as relações entre propósitos.

Claro, um usuário precisa estar autenticado e autorizado em relação às ações a serem tomadas, mas a autenticação e a autorização devem ser separadas do usuário.

Não é como se você tentasse autorizar / autenticar um não-usuário de qualquer maneira?

E, portanto, você deve considerar a divisão da implementação quando as responsabilidades de uma classe excederem seu objetivo. Afinal, os padrões de design também têm objetivos.

Dê uma olhada no GRASP quando tiver uma chance.

    
por 10.11.2011 / 10:43
fonte
1

"Princípio da Responsabilidade Única" não é o mesmo que "Princípio da Funcionalidade Única"

Muitas vezes - quando tentamos fazer isso da forma mais religiosa possível - tendemos a "quebrar" demais as aulas e ainda podemos violar o SRP de alguma forma, porque agora cada objeto pode precisar saber algo sobre o outro que se torna um motivo extra para mudança.

Não estou muito claro sobre a intenção das classes acima, mas acho que aqui estão alguns pontos -

  • Eu não sei se login e logout podem ser verdadeiramente independentes um do outro e se qualquer um deles pode ser independente de session

  • Não sei se você consideraria login e logout como classes ou métodos e por quê.

  • Eu não sei se UserManager fazendo create é qualquer forma diferente new user()

Eu acho que estou completamente errado em muitas coisas porque eu realmente não entendi a coisa toda. O segundo é um pouco melhor do que o primeiro, mas eu ainda posso estar errado.

Mas esse é precisamente o ponto - olhando para as classes que as intenções são muito claras - o sinal de que o SRP não está funcionando bem aqui.

    
por 11.11.2011 / 17:16
fonte
0

Uma maneira que eu gosto de fazer isso é começar a construir suas classes ignorando toda a sua estrutura.

Em seguida, siga a regra geral de 3.

  • Se você tiver mais de três funções públicas, divida-as em turmas separadas.
  • Se você tiver mais de três variáveis internas, divida-as em turmas separadas.
  • Se você tiver mais de 3 linhas funcionais em sua função, separe-as em diferentes funções.

Desta forma, você não precisa se preocupar se sua estrutura está correta ou não. Você pode ser fluido com o seu desenvolvimento. Esse processo de codificação é mais fácil se você tiver testes de unidade ou TDD em geral, mas não é 100% obrigatório. Também remove algumas sobrecargas mentais para o cérebro.

Acho que vou me preocupar tanto com a estrutura e agonizar tanto, que com o passar do tempo, estou muito apegado à estrutura e estou menos disposto a me adaptar quando preciso.

    
por 10.11.2011 / 13:30
fonte