SoC (Separation of Concerns) é a abreviatura do princípio pelo qual um sistema de software é dividido em áreas isoladas de responsabilidade. De acordo com Martin Fowler, a separação de responsabilidades é um elemento fundamental do código sustentável. O princípio SoC permite que os desenvolvedores alterem uma camada de uma aplicação sem afetar as outras, o que é especialmente importante no desenvolvimento móvel em equipa.
Principais pontos
SoC significa Separation of Concerns — «separação de responsabilidades» ou «separação de áreas de interesse». No contexto do desenvolvimento, o termo concern designa qualquer funcionalidade separável: renderização da interface do utilizador, processamento de cliques, validação de dados, comunicação em rede ou trabalho com a base de dados. O princípio SoC prescreve agrupar o código em torno destas áreas para que as alterações numa não afetem as outras.
A abreviatura SoC é amplamente utilizada na literatura técnica, discussões arquitetónicas e documentação de frameworks. Por exemplo, na documentação do Android Architecture Components, o SoC é mencionado repetidamente como motivação para separar ViewModel e View. Na comunidade iOS, o termo é usado ao discutir o problema do Massive View Controller, consequência direta da ausência de SoC.
É importante compreender que o SoC não é uma ação única, mas um processo contínuo. À medida que a aplicação cresce, surgem novas áreas de responsabilidade e a arquitetura deve ser revista. Uma boa base de código passa por várias iterações de separação antes de atingir um estado estável onde cada concern está isolado e gerível.
Separation of Concerns e a sua abreviatura SoC designam o mesmo princípio. A única diferença está no contexto de uso: o nome completo é usado em documentos formais, materiais educativos e ao explicar o conceito pela primeira vez a novos programadores. SoC é conveniente em discussões técnicas, revisões de código e documentação onde a brevidade é importante.
Num ambiente profissional, ambos os termos são intercambiáveis. Um programador pode dizer «aqui o SoC foi violado» ou «isto viola o Separation of Concerns» — o significado não muda. No entanto, em anúncios de emprego e requisitos de arquitetura, o nome completo é mais frequentemente usado, enquanto em chats e revisões de código usa-se a abreviatura. Conhecer ambas as variantes é necessário para uma entrada confortável na indústria.
Existe confusão terminológica: a abreviatura SoC também é usada no contexto de hardware para System-on-a-Chip (sistema num chip). No desenvolvimento móvel, o contexto é sempre claro pelo ambiente — se a discussão é sobre arquitetura de código, refere-se a Separation of Concerns. Neste artigo, SoC refere-se sempre ao princípio da separação de responsabilidades.
A arquitetura de três camadas é a forma mais comum de implementar SoC em aplicações móveis. Divide o código em Presentation (UI), Domain (lógica de negócio) e Data (fontes de dados). Cada camada contém tipos de classes estritamente definidos e está isolada das vizinhas através de interfaces. Esta abordagem é igualmente eficaz para projetos iOS, Android e Flutter.
View e ViewModel formam a camada de apresentação. A View é responsável por renderizar a interface e transmitir os eventos do utilizador. O ViewModel armazena o estado do ecrã e transforma os dados da camada Domain num formato pronto para exibição. O ViewModel não tem referências para Activity, Fragment ou UIViewController — isto garante SoC entre a UI e a lógica.
Por exemplo, no Android Jetpack, o ViewModel sobrevive à rotação do ecrã enquanto a UI é recriada. Sem SoC, seria necessário guardar o estado na Activity, misturando a gestão do ciclo de vida com os dados. O ViewModel resolve este problema de forma isolada, demonstrando uma implementação limpa do princípio da separação de responsabilidades.
Os Use Cases contêm regras de negócio independentes da plataforma. Esta camada não importa Android SDK, iOS UIKit nem Flutter framework. Um Use Case recebe dados do Repository, aplica lógica de negócio e retorna o resultado. Graças ao SoC, um mesmo Use Case pode ser reutilizado em diferentes ecrãs e plataformas.
Um exemplo clássico é o ValidateAndSaveUseCase para um formulário de registo. Ele valida o e-mail e a palavra-passe, chama o UserRepository para guardar e retorna um ValidationResult. Nem a UI nem a base de dados conhecem as regras de validação — estão concentradas num único local, facilitando a sua alteração.
O Repository abstrai as fontes de dados do resto da aplicação. O ViewModel não sabe de onde vêm os dados — se de REST API, GraphQL, base de dados local ou cache. O Repository decide qual fonte usar e oculta esta lógica por detrás de uma interface. Isto é SoC entre a obtenção e o consumo de dados.
O DataSource proporciona uma separação ainda mais profunda: o RemoteDataSource é responsável apenas pelos pedidos HTTP, o LocalDataSource pelo trabalho com Room, CoreData ou SharedPreferences. O Repository combina-os aplicando estratégias de cache. Cada DataSource pode ser substituído de forma independente, o que é crítico ao migrar entre servidores ou bases de dados.
Este sistema multinível de DataSources implementa SoC ao nível da infraestrutura: a comunicação em rede, o armazenamento local e a cache são concerns separados, cada um com a sua própria lógica e ciclo de vida. Ao substituir um cliente HTTP, apenas o RemoteDataSource muda, enquanto o Repository e as camadas superiores permanecem intactos, confirmando o valor prático da separação de responsabilidades.
MVP (Model-View-Presenter) foi um dos primeiros padrões a implementar explicitamente SoC no desenvolvimento móvel. O Presenter contém a lógica e controla a View através de uma interface. A View é passiva — apenas exibe o que o Presenter lhe diz. A separação simplifica os testes: o Presenter é testado sem emulador e a View permanece tão simples que não há nada para quebrar.
MVVM adicionou a ligação reativa: a View subscreve as alterações do ViewModel através de Observable ou StateFlow. O ViewModel não mantém uma referência para a View, eliminando o risco de fugas de memória e separando ainda mais os concerns. No Android, o MVVM tornou-se o padrão graças ao Jetpack ViewModel e LiveData; no iOS, graças ao Combine e RxSwift.
Clean Architecture de Robert Martin leva o SoC a uma separação radical em anéis. O anel exterior (frameworks e drivers) depende do interior (entidades), mas não o contrário. Na prática, os projetos móveis raramente implementam todos os quatro anéis — basta as camadas Domain e Data à volta da Presentation. Mas o princípio da «dependência para dentro» oferece vantagens significativas ao mudar de frameworks.
// View — apenas exibição, sem lógica
final class LoginViewController: UIViewController {
let viewModel: LoginViewModel
func loginTapped() {
viewModel.login(emailField.text, passwordField.text)
}
}
// ViewModel — contém a lógica do ecrã, não conhece UIKit
final class LoginViewModel {
private let loginUseCase: LoginUseCase
func login(email: String?, password: String?) {
loginUseCase.execute(email, password)
}
}
// Use Case — lógica de negócio, independente da plataforma
final class LoginUseCase {
private let repo: AuthRepository
func execute(email: String?, password: String?) {
guard let e = email, let p = password else { return }
repo.authenticate(e, p)
}
}
O exemplo mostra três níveis de SoC: o LoginViewController apenas transmite eventos, o LoginViewModel gere o estado e o LoginUseCase contém as regras de negócio. Cada classe é testada de forma independente e a mudança do framework de UI não afeta o Use Case.
Massive View Controller é a violação mais frequente do SoC em iOS. Uma classe que gere a UI, processa pedidos de rede, analisa JSON e persiste dados viola o princípio a todos os níveis. A solução é extrair cada responsabilidade para um componente separado: NetworkingService, JSONParser, CoreDataStack, deixando ao ViewController apenas a gestão da View.
No Android, um problema semelhante é a God Activity ou God Fragment. Uma atividade que carrega dados, valida formulários, mostra diálogos e atualiza a UI. Resolve-se introduzindo ViewModel e Repository, que assumem a gestão do estado e dos dados. O ViewModel também protege contra a perda de dados durante a rotação do ecrã.
A terceira violação é misturar código de plataforma e de negócio. Por exemplo, colocar um pedido HTTP diretamente numa SwiftUI View ou Android Composable. Isto torna o código não portável e difícil de testar. A abordagem correta é mover o pedido para um Repository, que é chamado através de um Use Case, enquanto a View apenas subscreve o resultado. Cada elemento do sistema resolve a sua própria tarefa e não ultrapassa os seus limites.
Perguntas frequentes
Não. SoC é um princípio mais geral de dividir um sistema em áreas de responsabilidade. SOLID é um conjunto de cinco regras específicas para design orientado a objetos. O primeiro princípio do SOLID (Single Responsibility) é um caso particular de SoC ao nível de uma única classe.
Use a regra de uma única razão para mudar (Single Responsibility). Se uma classe muda devido a alterações na UI, formato de dados e regras de negócio — o SoC foi violado. Ferramentas como ArchTest (Android) e StrictConcurrency (iOS) ajudam a detetar estas violações automaticamente.
Em teoria, as camadas adicionais adicionam chamadas indiretas, mas na prática o impacto no desempenho de uma aplicação móvel é insignificante. O compilador inline muitas chamadas e as otimizações JIT e AOT eliminam a sobrecarga. A maintainability do código ganha muito mais do que se perde em abstrações.
Comece por extrair os pedidos de rede da UI para um Repository. Depois mova a lógica de negócio para Use Cases. Use injeção de dependências para ligar as camadas. Faça as alterações iterativamente, cobrindo o novo código com testes — isto garante que a refatoração não quebra a funcionalidade existente.
Em protótipos, o SoC pode ser violado por rapidez. Mas se um protótipo passa para desenvolvimento de produção, o custo da refatoração pode superar o benefício de um início rápido. O ideal é manter uma separação mínima (UI e dados) mesmo num protótipo para evitar reescrever tudo do zero no lançamento.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também