Você provavelmente já viu código com tudo dentro de um único arquivo de view de 800 linhas.
No código da view que desenha a tela há chamadas de API; ao lado, lógica para calcular descontos; abaixo, funções para formatar datas; e, espalhados pelo arquivo, envios de eventos de analytics. Para corrigir qualquer coisa, é preciso ler as 800 linhas inteiras.
O princípio violado por esse tipo de arquivo é a separação de responsabilidades, Separation of Concerns em inglês. Este é o último capítulo da série sobre princípios de desenvolvimento.
A separação de responsabilidades (SoC) determina que o programa seja dividido em unidades com responsabilidades diferentes, para que cada parte trate de apenas uma responsabilidade.
“Responsabilidade” é o tipo de tarefa com que o programa precisa se preocupar. Como exibir a tela, de onde obter os dados e como aplicar as regras de negócio são responsabilidades diferentes.
O termo foi criado pelo cientista da computação Dijkstra, que o expressou assim em um texto de 1974.
Pensar concentrando-se em um único aspecto por vez. Essa é a única técnica eficaz de pensamento que conheço.
A mente humana não consegue lidar com várias responsabilidades ao mesmo tempo. Por isso, cada trecho de código deve conter apenas uma.
Um caso conhecido: HTML, CSS e JS
Se você já trabalhou com desenvolvimento web, então já usa separação de responsabilidades todos os dias.
| Tecnologia | Responsabilidade |
|---|---|
| HTML | Estrutura — o que existe |
| CSS | Apresentação — como aparece |
| JavaScript | Comportamento — como reage |
Se, como antigamente, enchermos as tags HTML com os atributos style e onclick, até mudar a cor de um botão exige procurar no HTML. Ao dividir em três arquivos, o designer olha apenas o CSS, e quem cuida da marcação, apenas o HTML.
A estrutura controller-service-repository do backend e a separação entre view, view model e camada de dados no iOS seguem o mesmo princípio. MVC e arquiteturas em camadas são, no fim, padrões que formalizam a separação de responsabilidades.
Operando aquela view de 800 linhas
Vamos separar por responsabilidade a view de 800 linhas que vimos antes.
// Before: Todas as responsabilidades em um arquivo
struct ProductPage: View {
// Responsabilidade 1: Obter dados (chamadas de rede, carregamento e tratamento de erros 150linhas)
// Responsabilidade 2: Regras de negócio (cálculo de descontos e estoque 200linhas)
// Responsabilidade 3: Eventos de analytics (rastreamento de abas 100linhas)
// Responsabilidade 4: Desenhar a tela (body 350linhas)
}
// After: Cada responsabilidade encontra seu próprio lugar
ProductStore(id:) // Obter dados
calcDiscount(product, user) // Regras de negócio (função pura)
Tracker.track("product") // Eventos de analytics
struct ProductPage: View { // Apenas desenhar a tela
@State private var store: ProductStore
var body: some View {
let price = calcDiscount(store.product, user)
...
}
}
Depois de separar, as vantagens ficam claras. Se a política de descontos mudar, basta olhar calcDiscount; como essa é uma função pura, independente da tela, ela também é fácil de testar. Se a especificação da API mudar, basta alterar ProductStore. Comparado a ler as 800 linhas inteiras, o escopo da alteração cai para um décimo.
Até onde devemos separar?
A parte mais difícil da separação de responsabilidades é decidir onde traçar a fronteira. Se separarmos demais, teremos um labirinto que exige navegar por dezenas de arquivos.
Meu critério é o motivo da mudança. É a mesma pergunta que vimos ao tratar do SRP de SOLID.
Estes dois códigos mudam pelo mesmo motivo e ao mesmo tempo?
A política de descontos e o layout da tela mudam por motivos diferentes, então devem ser separados. Já o botão e seu handler de toque quase sempre mudam juntos, então ficam juntos. Sob essa perspectiva, o fato de SwiftUI reunir estrutura, estilo e comportamento em um arquivo por view não é uma contradição. As responsabilidades foram redefinidas pela unidade que muda em conjunto, não pelo tipo de tecnologia.
Encerrando a série
Este é o ponto principal que fica da separação de responsabilidades.
- Faça cada trecho de código tratar de apenas uma responsabilidade. A mente humana não faz multitarefa.
- Na prática, trace as fronteiras pela “unidade que muda em conjunto”, não pelo tipo de tecnologia.
- Separar demais cria um labirinto. A separação em si não pode virar o objetivo.
Com isso, termina a série sobre princípios de desenvolvimento: KISS (manter simples), DRY (manter o conhecimento em um só lugar), YAGNI (apenas o necessário agora), SOLID (reduzir o impacto das mudanças), mínimo espanto (comportar-se como esperado) e separação de responsabilidades (uma coisa por vez).
Olhando para trás, os seis princípios apontam para o mesmo lugar. O código é lido por pessoas, não por computadores, e código bom é código fácil de alterar. Mesmo que você esqueça os nomes dos princípios, guarde esta frase.

