OCP — Princípios, abertura para extensão e fechamento para modificação

Autor: IT Sectr Publicado: 2026-05-11 Tempo de leitura: 9 min

OCP (Open/Closed Principle) é o segundo princípio do SOLID, que determina: entidades de software devem estar abertas para extensão mas fechadas para modificação. Este princípio, formulado por Bertrand Meyer em 1988, permite adicionar novas funcionalidades sem alterar o código existente. De acordo com o livro de Robert Martin Clean Architecture (2017), o princípio de abertura é implementado através de abstrações e polimorfismo, minimizando o risco de erros de regressão.

Pontos Principais

  • OCP — o princípio de abertura para extensão e fechamento para modificação
  • Extensão é implementada através de abstrações, interfaces e polimorfismo
  • Modificação do código existente é proibida — novas funcionalidades são adicionadas sem alterar classes antigas
  • Polimorfismo — o mecanismo chave do OCP em linguagens orientadas a objetos
  • Violar o OCP leva a mudanças em cascata ao adicionar novos requisitos

O que é OCP (Open/Closed Principle)?

OCP (Open/Closed Principle) — o princípio de abertura para extensão e fechamento para modificação. Classes, módulos e funções devem ser projetados para que novos comportamentos possam ser adicionados sem alterar seu código fonte. A extensão é alcançada através de herança, composição ou substituição de implementações de interfaces.

Bertrand Meyer em seu livro Object-Oriented Software Construction (1988) descreveu o OCP pela primeira vez através de herança: a classe base permanece inalterada, enquanto as subclasses estendem seu comportamento. A interpretação moderna do OCP, proposta por Robert Martin, baseia-se em polimorfismo e interfaces: em vez de herança, são usados contratos abstratos.

A diferença entre as abordagens é significativa. A herança cria um acoplamento forte entre classes base e derivadas. Interfaces e composição fornecem flexibilidade: a implementação pode ser trocada sem alterar o código cliente. OCP moderno é sobre abstração, não sobre herança.

Polimorfismo como base do OCP

OCP polimórfico usa classes abstratas ou interfaces para definir um contrato. O código cliente trabalha com a abstração sem conhecer a implementação concreta. Nova funcionalidade é adicionada criando uma nova classe que implementa a mesma interface — sem uma única alteração no código existente. Isso torna o sistema resistente a mudanças e previsível para extensão.

No desenvolvimento móvel, esta abordagem é onipresente: o padrão Strategy permite trocar algoritmos (compressão de imagem, cache, autenticação) através de uma interface única. Adicionar uma nova estratégia não requer alterar o código que a utiliza.

Como implementar o princípio de abertura e fechamento

Implementar OCP começa isolando o comportamento variável em uma abstração. Se houver uma construção switch ou uma cadeia if-else verificando o tipo de um objeto no código — é um sinal para aplicar OCP. Cada ramo condicional potencialmente requer adicionar um novo ramo ao estender.

O processo de refatoração sob OCP inclui três passos: identificar o aspecto variável (o que pode ser estendido), isolá-lo em uma interface ou classe abstrata, reescrever o código cliente para trabalhar com a abstração em vez da classe concreta. Após isso, novas funcionalidades são adicionadas sem alterar o cliente.

Um esclarecimento importante: fechamento para modificação não é absoluto. Se uma mudança de requisito afetar a própria abstração ou o contrato — a mudança é inevitável. OCP protege contra mudanças nas implementações, não nos contratos. Um bom design assume que os contratos são estáveis e as implementações são variáveis.

Ao avaliar a compatibilidade OCP de uma arquitetura, é útil observar os pontos de extensão. Cada ponto onde um desenvolvedor adiciona if-else ou switch para um novo tipo é candidato a abstração. Um sistema projetado segundo OCP tem pontos de extensão previsíveis: interfaces com documentação que diz "implemente esta interface para adicionar um novo tipo". No Android, um exemplo claro é o padrão Factory com ViewModelProvider.Factory — adicionar um novo tipo de ViewModel não requer alterar fábricas existentes.

Estratégias e padrões para OCP

Os padrões mais eficazes para cumprir OCP no desenvolvimento móvel incluem Strategy, Template Method, Decorator e Factory. Cada um resolve o problema de estender comportamento sem modificar código existente através de diferentes mecanismos de design orientado a objetos.

Strategy permite trocar algoritmos em tempo real através de uma interface comum. No desenvolvimento iOS, estratégias são usadas para animações e validação de formulários. Template Method define o esqueleto de um algoritmo em uma classe base, e as subclasses sobrescrevem os passos — adequado para telas com estrutura comum mas conteúdo diferente.

Decorator adiciona dinamicamente comportamento a um objeto sem alterar sua classe. No Android, Decorator é usado para envolver um Repository com uma camada de cache ou registro. Factory Method cria objetos através de uma interface, permitindo que subclasses decidam qual classe instanciar — a base da criação de dependências compatível com OCP.

Escolha de estratégia para um projeto móvel

A escolha do padrão depende da estabilidade do comportamento sendo estendido. Strategy é ideal quando algoritmos são substituídos completamente. Template Method — quando a estrutura é fixa mas os passos variam. Decorator — quando a extensão deve ser transparente para o cliente. Para a maioria dos cenários em Android e iOS, Strategy + injeção de dependência é suficiente.

Aplicar estes padrões sem OCP é tecnicamente possível mas perde o sentido. É o OCP que justifica porque introduzimos um nível adicional de abstração: para que o sistema possa crescer sem reescrever código existente.

Exemplos de OCP em aplicações móveis

Consideremos um exemplo Android com processamento de pagamentos. Sem OCP, cada novo sistema de pagamento requer alterações na classe manipuladora. Com OCP, uma nova implementação de interface é adicionada sem modificar o código existente.

kotlin
// Violação de OCP: switch requer modificação ao adicionar um novo sistema
class BadPaymentProcessor {
    fun process(type: String) {
        when (type) {
            "card" -> // processamento de cartão
            "paypal" -> // processamento de PayPal
        }
    }
}

// Design compatível com OCP
interface PaymentMethod {
    fun pay(amount: Double)
}

class CardPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

class PayPalPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

// Novo sistema — nova classe, sem alterar código existente
class ApplePayPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

Um exemplo iOS com validação de campos de texto demonstra a mesma lógica através de protocolos Swift:

swift
// Validação compatível com OCP
protocol ValidationRule {
    func validate(_ input: String) -> Bool
}

struct EmailRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.contains("@")
    }
}

struct PhoneRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.count == 11
    }
}

// Adicionar uma nova regra não requer alterar o código do validador
struct PasswordRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.count >= 8
    }
}

A vantagem chave do OCP nestes exemplos: adicionar ApplePay ou PasswordRule não requer modificar classes existentes. O código se expande horizontalmente — através de novos arquivos, não alterando os antigos. Isso reduz o risco de regressão e acelera a implementação de novas funcionalidades.

Erros típicos ao violar OCP

A violação mais comum é uma construção switch ou when baseada no tipo do objeto. Cada vez que um novo tipo é adicionado, é necessário encontrar todos esses switch no código e adicionar um novo ramo. Um switch esquecido é um erro em tempo de execução difícil de detectar em tempo de compilação.

No desenvolvimento móvel, OCP é violado ao usar classes enum gigantes com métodos que dependem do valor do enum. Adicionar um novo elemento enum requer alterar cada switch em todo o projeto. A alternativa é o polimorfismo através de uma interface, onde cada tipo implementa seu próprio comportamento.

Outra violação típica é o God Adapter: RecyclerView.Adapter (Android) ou UITableViewDataSource (iOS) que manipula diferentes tipos de célula através de if-else. Cada novo tipo de célula requer estender o adaptador. A solução é um ViewHolder polimórfico com um método bind comum, onde cada tipo de célula é responsável por sua própria renderização.

Como evitar violar OCP

Medidas preventivas incluem: evitar switch baseado em tipo em favor do polimorfismo, injetar dependências através de interfaces e usar o padrão Factory para criar objetos conforme configuração. Analisar o código em busca de "comutadores por tipo" é parte obrigatória da revisão de código em times orientados a OCP.

Refatorar uma violação existente de OCP é feito através de Replace Conditional with Polymorphism: cada ramo condicional torna-se uma classe separada implementando uma interface comum. O código cliente é reescrito para trabalhar com a interface, e a implementação concreta é fornecida através de uma fábrica ou contêiner DI.

É importante entender que OCP e polimorfismo não resolvem todos os problemas de extensão. Se a arquitetura for escolhida incorretamente, adicionar nova funcionalidade exigirá alterar não apenas implementações mas também contratos. Uma boa arquitetura prevê direções de extensão e coloca abstrações exatamente nesses pontos. Investimentos em OCP compensam mais quanto mais tempo o projeto vive e quanto mais frequentemente os requisitos de módulos específicos mudam.

Perguntas Frequentes

OCP significa que o código não pode ser alterado de forma alguma?

Não. OCP proíbe alterar o código existente ao adicionar novas funcionalidades relacionadas à mesma abstração. Alterar um contrato, corrigir bugs e refatorar não são violações do OCP — o princípio protege contra mudanças em cascata durante a extensão.

Como o OCP se relaciona com o padrão Strategy?

Strategy é uma implementação direta do OCP. A interface de estratégia define o contrato, o cliente depende da abstração, e as estratégias concretas implementam o comportamento variável. Adicionar uma nova estratégia não requer alterar o cliente — isto é abertura para extensão com fechamento para modificação.

É possível cumprir OCP sem interfaces?

Sim, através de herança e Template Method: a classe base define o esqueleto do algoritmo e as subclasses sobrescrevem os passos. No entanto, a herança cria um acoplamento forte e é menos flexível que interfaces. No desenvolvimento moderno, interfaces e composição são consideradas a forma preferida de implementar OCP.

Como o OCP afeta os testes?

Código compatível com OCP simplifica os testes: cada implementação de interface é testada isoladamente. O código cliente é testado com uma implementação mock, permitindo verificar a lógica sem vincular-se a um comportamento específico. Expandir o sistema não requer reescrever os testes existentes.

Deve-se sempre buscar OCP?

Não. OCP é justificado quando a extensão funcional é previsível. Para código estável que não está planejado para ser estendido, abstração adicional é excessiva. YAGNI (You Ain't Gonna Need It) é um bom contrapeso ao OCP: a abstração é introduzida quando uma segunda variante de comportamento aparece, não preventivamente.

Resumo

  • OCP (Open/Closed Principle) — o princípio de abertura para extensão e fechamento para modificação
  • Extensão é implementada através de interfaces, polimorfismo e composição em vez de herança
  • Switch por tipo — o principal antipadrão que viola OCP e requer alterações com cada novo tipo
  • Strategy e Template Method — os principais padrões para cumprir OCP em projetos móveis
  • Polimorfismo substitui construções condicionais e torna o código extensível sem modificação
  • Refatorar uma violação de OCP é feito através de Replace Conditional with Polymorphism
  • YAGNI limita OCP: a abstração é introduzida quando uma segunda implementação aparece, não antecipadamente

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.

Discutir o projeto

Leia também