MVC: O Controlador quebra o Princípio da Responsabilidade Única?

15

O Princípio da Responsabilidade Única afirma que "uma turma deve ter um motivo para a mudança".

No padrão MVC, o trabalho do Controlador é mediar entre a Visualização e o Modelo. Ele oferece uma interface para o View para relatar ações feitas pelo usuário na GUI (por exemplo, permitindo que o View chame controller.specificButtonPressed() ), e é capaz de chamar os métodos apropriados no Model para manipular seus dados ou invocar suas operações. (por exemplo, model.doSomething() ).

Isso significa que:

  • O Controller precisa saber sobre a GUI, para oferecer à View uma interface adequada para relatar as ações do usuário.
  • Ele também precisa saber sobre a lógica no Modelo, para poder invocar os métodos apropriados no Modelo.

Isso significa que há dois motivos para alterar : uma alteração na GUI e uma alteração na lógica de negócios.

Se a GUI mudar, por ex. um novo botão é adicionado, o Controlador pode precisar adicionar um novo método para permitir que o View informe um usuário pressionando este botão.

E se a lógica de negócios no Modelo for alterada, o Controlador poderá ter que mudar para invocar os métodos corretos no Modelo.

Portanto, o Controlador tem dois motivos possíveis para alterar . Isso quebra o SRP?

    
por Aviv Cohn 04.05.2014 / 00:01
fonte

5 respostas

12

Se você continuar a raciocinar sobre o SRP, perceberá que "responsabilidade única" é na verdade um termo esponjoso. Nosso cérebro humano é de alguma forma capaz de distinguir entre responsabilidades diferentes e responsabilidades múltiplas que podem ser abstraídas em uma responsabilidade "geral". Por exemplo, imagine em uma família comum de 4 pessoas, há um membro da família responsável por fazer o café da manhã. Agora, para fazer isso, é preciso ferver ovos e torrar pão e, claro, preparar uma xícara de chá verde saudável (sim, o chá verde é o melhor). Desta forma, você pode quebrar "fazendo café da manhã" em pedaços menores que são juntos abstraídos para "fazer café da manhã". Observe que cada peça é também uma responsabilidade que poderia, por exemplo, ser delegada a outra pessoa.

Voltar para o MVC: se a mediação entre modelo e visualização não for uma responsabilidade, mas duas, qual seria a próxima camada de abstração acima, combinando essas duas? Se você não consegue encontrar um, você não o abstraiu corretamente ou não há nenhum que signifique que você entendeu tudo bem. E eu sinto que é o caso de um controlador, lidando com uma visão e um modelo.

    
por 04.05.2014 / 01:11
fonte
8

Se uma turma tem "dois possíveis motivos para mudar", então sim, viola o SRP.

Um controlador geralmente deve ser leve e ter a responsabilidade única de manipular o domínio / modelo em resposta a algum evento orientado por GUI. Podemos considerar cada uma dessas manipulações como basicamente casos de uso ou recursos.

Se um novo botão for adicionado na GUI, o controlador só precisará alterar se esse novo botão representar algum novo recurso (isto é, contrário ao mesmo botão que existia na tela 1, mas ainda não existia na tela 2) e é então adicionado à tela 2). Também precisaria haver uma nova mudança correspondente no modelo para suportar essa nova funcionalidade / recurso. O controlador ainda tem a responsabilidade de manipular o domínio / modelo em resposta a algum evento orientado por GUI.

Se a lógica de negócios no modelo for alterada devido a um bug ser corrigido e exigir que o controlador seja alterado, esse é um caso especial (ou talvez o modelo esteja violando o principal de abertura aberta). Se a lógica de negócios no modelo for alterada para suportar alguma nova funcionalidade / recurso, isso não impactará necessariamente o controlador - somente se o controlador precisar expor esse recurso (o que quase sempre seria o caso, caso contrário, por que ele seria adicionado a o modelo de domínio se não for usado). Portanto, nesse caso, o controlador também precisa ser modificado para suportar a manipulação do modelo de domínio dessa nova maneira em resposta a algum evento orientado por GUI.

Se o controlador tiver que mudar porque, digamos, a camada de persistência é alterada de um arquivo simples para um banco de dados, o controlador certamente está violando o SRP. Se o controlador sempre funciona na mesma camada de abstração, isso pode ajudar a alcançar o SRP.

    
por 04.05.2014 / 00:49
fonte
4

O controlador não viola o SRP. Conforme você declara, sua responsabilidade é mediar entre os modelos e a visão.

Dito isso, o problema com o seu exemplo é que você está vinculando os métodos do controlador à lógica na exibição, ou seja, controller.specificButtonPressed . Nomear os métodos dessa maneira liga o controlador à sua GUI, você não conseguiu abstrair adequadamente as coisas. O controlador deve executar ações específicas, ou seja, controller.saveData ou controller.retrieveEntry . Adicionar um novo botão na GUI não significa necessariamente adicionar um novo método ao controlador.

Pressionando um botão na visão, significa fazer algo, mas seja o que for, isso poderia facilmente ter sido disparado em qualquer número de outras vias ou até mesmo através da visão.

Do artigo da Wikipedia sobre SRP

Martin defines a responsibility as a reason to change, and concludes that a class or module should have one, and only one, reason to change. As an example, consider a module that compiles and prints a report. Such a module can be changed for two reasons. First, the content of the report can change. Second, the format of the report can change. These two things change for very different causes; one substantive, and one cosmetic. The single responsibility principle says that these two aspects of the problem are really two separate responsibilities, and should therefore be in separate classes or modules. It would be a bad design to couple two things that change for different reasons at different times.

O controlador não está preocupado com o que está na exibição apenas quando um de seus métodos é chamado para fornecer dados especificados para a exibição. Ele só precisa saber sobre a funcionalidade do modelo até onde ele sabe que precisa chamar métodos que eles terão. Não sabe nada mais que isso.

Saber que um objeto tem um método disponível para chamar não é o mesmo que saber sua funcionalidade.

    
por 04.05.2014 / 02:49
fonte
1

A única responsabilidade dos controladores é ser o contrato que medeia entre a visão e o modelo. A View deve ser responsável apenas pela exibição, o modelo deve ser responsável apenas pela lógica de negócios. A responsabilidade dos controladores é colmatar essas duas responsabilidades.

É tudo muito bom, mas se aventurar um pouco longe da academia; Um controlador no MVC é geralmente composto de muitos métodos de ação menores. Essas ações geralmente correspondem a coisas que uma coisa pode fazer. Se estou vendendo produtos, provavelmente terei um ProductController. Esse controlador terá ações como GetReviews, ShowSpecs, AddToCart ect ...

A exibição tem o SRP de exibir a interface do usuário e parte dessa interface inclui um botão que diz AddToCart.

O controlador tem o SRP de conhecer todas as visões e modelos envolvidos no processo.

Os controladores AddToCart Action têm o SRP específico de conhecer todos que precisam estar envolvidos quando um item é adicionado a um carrinho.

O Modelo do Produto tem o SRP de modelagem da lógica do produto, e o Modelo do ShoppingCart tem o SRP de modelagem de como os itens são salvos para check-out posterior. O modelo do usuário tem um SRP de modelagem do usuário que está adicionando coisas ao carrinho.

Você pode e deve estar reutilizando modelos para realizar seus negócios, e esses modelos precisam ser acoplados em algum momento de seu código. O controlador controla cada maneira única que o acoplamento acontece.

    
por 02.07.2017 / 06:05
fonte
0

Os controladores na verdade têm apenas uma responsabilidade: alterar o estado dos aplicativos com base na entrada do usuário.

A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its associated view to change the view's presentation of the model (e.g., by scrolling through a document).

source: wikipedia

Se, ao invés disso, você está tendo "controladores" em estilo Rails (que manipulam instâncias de registro ativas e modelos estúpidos) , então é claro que estão quebrando o SRP.

Então, novamente, aplicativos estilo Rails não são realmente MVC para começar.

    
por 05.05.2014 / 22:25
fonte