O que é?
Object Calisthenics é um conjunto de 9 regras propostas por Jeff Bay (na obra The ThoughtWorks Anthology) para exercitar boas práticas em programação orientada a objetos (OOP). William Durand+2developerhandbook.stakater.com+2
O nome “calisthenics” remete a exercícios físicos, a ideia é que, assim como no treino, ao praticar essas regras você fortalece o estilo de código. developerhandbook.stakater.com+1
Essas regras não são leis, são exercícios mentais e técnicos para evoluir o design do seu código. O objetivo é forçar o desenvolvedor a pensar melhor sobre responsabilidades, encapsulamento e legibilidade.
Essas regras têm como foco melhorar coisas como: legibilidade, testabilidade, manutenibilidade, compreensão da estrutura do código. William Durand+1
As 9 regras
Aqui vão as regras, com explicação resumida (há variações em artigos, mas o núcleo é esse):
- Apenas um nível de indentação por método (“Only one level of indentation per method”) — evitar muitos níveis de if, loop, etc., dentro de um método. developerhandbook.stakater.com
- Não usar a palavra-chave
else(“Don’t use the ELSE keyword”) — favorecer guard clauses ou retornos antecipados em vez de else’s aninhados. William Durand+1 - Encapsular todos os primitivos e strings (“Wrap all primitives and strings”) — evitar usar diretamente “int”, “String”, “float” etc, sem uma classe adequada para o domínio. DEV Community
- Coleções de primeira classe (“First-class collections”) — se você tem uma coleção (lista/array) que é parte de uma entidade, crie uma classe específica para essa coleção. developerhandbook.stakater.com
- Uma chamada de método (“dot”) por linha (“One dot per line”) — evita encadeamento excessivo (“a.getB().getC().getD()”) que viola o princípio de Lei de Deméter. DEV Community
- Não abreviar nomes (“Don’t abbreviate”) — favorece nomes claros, compreensíveis, não abreviações obscuras. DEV Community
- Mantenha todas as entidades pequenas (“Keep all entities small”) — classes/metódos não devem ser grandes com muitas responsabilidades. William Durand
- Não ter classes com mais de duas variáveis de instância (“No classes with more than two instance variables”) — limite o número de variáveis de instância para manter coesão. DEV Community
- Sem getters/setters/propriedades (“No getters/setters/properties”) — evitar expor estado interno; prefira métodos que façam parte do comportamento da entidade. developerhandbook.stakater.com
Por que isso importa
Como engenheiro de software que trabalha com arquitetura e liderança de times, aplicar práticas como Object Calisthenics pode ajudar a elevar a qualidade dos sistemas, facilitar manutenção, reduzir acoplamento, promover código mais expressivo e sustentável. Algumas vantagens:
- Força você a pensar em abstrações melhores, não apenas em fazer funcionar.
- Ajuda no design para quem vai manter o código depois — facilita leitura, refatorações, testes.
- Auxilia no estabelecimento de disciplina de equipe — se todos acordarem algumas dessas regras, o estilo se homogeniza.
- Pode revelar “code smells” escondidos: classes grandes demais, métodos com muitas responsabilidades, lógica espaguete, etc.
Limitações / cuidados
- As regras não são leis absolutas: como muitos autores apontam, existem casos onde “ultrapassar” uma delas faz sentido para pragmatismo. DEV Community
- Algumas regras podem parecer exageradas ou difíceis de aplicar em contextos específicos (ex: código legado, frameworks que exigem getters/setters, integração com bibliotecas externas).
- Aplicar todas as 9 de uma vez pode ser muito radical; melhor introduzir gradualmente.
- Fazer “por protocolo” sem entender o porquê pode gerar frustração.
Boas práticas e benefícios
- Código mais expressivo e coeso
- Redução de acoplamento e complexidade
- Maior facilidade para testar e manter
- Melhor compreensão do domínio
- Facilita refatorações e onboarding de novos devs
Como aplicar em equipes
- Comece com 1 ou 2 regras — não tente aplicar todas de uma vez.
- Promova code reviews voltados a práticas de design.
- Documente exceções (quando quebrar uma regra, justifique).
- Use como exercício em Dojos e Pair Programming.
- Reforce a ideia de que código é comunicação, não apenas execução.
- Escolha uma ou duas regras para pilotar no próximo refactoring de módulo. Por exemplo: “um nível de indentação por método” + “uma chamada de método por linha”.
- Promova um workshop interno para apresentar as regras e discutir como se aplicam no código atual.
- Defina checkpoints em code reviews para verificar aderência às regras selecionadas.
- Documente exceções, por que se foge de uma regra em determinado caso, qual o trade-off.
- Meça o impacto qualitativo: é mais fácil ler, modificar, testar o código?
- Inclua nas definições de arquitetura / coding-standards da equipe as regras que forem adotadas regularmente.
🧩 Exemplos em Java
“Código limpo não nasce, se treina.” — Jeff Bay
Esses são os 9 exercícios de design orientado a objetos, com exemplos práticos.
1. Only One Level of Indentation per Method
Apenas um nível de indentação por método
❌ Errado
void processOrders(List<Order> orders) {
for (Order order : orders) {
if (order.isValid()) {
if (order.hasStock()) {
order.ship();
}
}
}
}✅ Correto
void processOrders(List<Order> orders) {
for (Order order : orders) {
process(order);
}
}
private void process(Order order) {
if (!order.isValid()) return;
if (!order.hasStock()) return;
order.ship();
}🔹 Mantém a lógica simples, clara e com um único nível.
2. Don’t Use the ELSE Keyword
Evite o uso de
else
❌ Errado
if (user.isActive()) {
sendEmail(user);
} else {
deactivateAccount(user);
}✅ Correto
if (!user.isActive()) {
deactivateAccount(user);
return;
}
sendEmail(user);🔹 Usar “guard clauses” reduz complexidade e melhora legibilidade.
3. Wrap All Primitives and Strings
Encapsule todos os primitivos e strings
❌ Errado
public class Product {
private String name;
private double price;
}✅ Correto
public class ProductName {
private final String value;
public ProductName(String value) {
if (value == null || value.isBlank())
throw new IllegalArgumentException("Invalid name");
this.value = value;
}
public String value() {
return value;
}
}
public class Price {
private final BigDecimal value;
public Price(BigDecimal value) {
if (value.compareTo(BigDecimal.ZERO) < 0)
throw new IllegalArgumentException("Negative price");
this.value = value;
}
public BigDecimal value() {
return value;
}
}
public class Product {
private final ProductName name;
private final Price price;
}🔹 Evita lógica repetida e dá semântica ao domínio.
4. First-Class Collections
Crie classes específicas para coleções
❌ Errado
public class Order {
private List<Item> items;
}✅ Correto
public class Items {
private final List<Item> list = new ArrayList<>();
public void add(Item item) {
list.add(item);
}
public Money total() {
return list.stream().map(Item::price).reduce(Money.ZERO, Money::add); }
public int size() {
return list.size();
}
}
public class Order {
private final Items items;
}🔹 A coleção passa a ter comportamento e regras próprias.
5. One Dot per Line
Uma única chamada de método por linha
❌ Errado
customer.getOrder().getPayment().process();
✅ Correto
Order order = customer.getOrder();
Payment payment = order.getPayment(); payment.process();Ou melhor ainda:
customer.processPayment();🔹 Reduz acoplamento e segue a Lei de Deméter.
6. Don’t Abbreviate
Não use abreviações
❌ Errado
int qty; String addr;
✅ Correto
int quantity; String address;
🔹 Evita confusão e melhora legibilidade.
7. Keep All Entities Small
Mantenha classes e métodos pequenos
❌ Errado
public class OrderService { // 300 linhas de regras de negócio misturadas }
✅ Correto
public class OrderValidator { ... } public class OrderCalculator { ... } public class OrderProcessor { ... }
🔹 Aplica SRP (Single Responsibility Principle).
8. No Classes with More Than Two Instance Variables
Máximo de duas variáveis por classe
❌ Errado
public class User { private String name; private String email; private int age; private String phone; }✅ Correto
public class ContactInfo { private final String email; private final String phone; } public class User { private final Name name; private final ContactInfo contact; }🔹 Classes com poucos atributos têm mais coesão e menos dependência.
9. No Getters/Setters/Properties
Evite expor estado interno
❌ Errado
public class Rectangle {
private int width;
private int height;
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}✅ Correto
public class Rectangle {
private final int width;
private final int height;
public int area() {
return width * height;
}
public boolean isSquare() {
return width == height;
}
}🔹 Comportamento > dados. O objeto sabe se virar sozinho.
🧠 Conclusão
O Object Calisthenics é mais do que um conjunto de regras —
é uma filosofia de design orientado a clareza, responsabilidade e propósito.
Esses exercícios ajudam a fortalecer a mentalidade de Clean Code e preparar o terreno para uma arquitetura sustentável a longo prazo.
“Código bom é aquele que você entende amanhã.” 🧠💡
Essas regras não são leis absolutas, mas exercícios de design que:
- Ajudam a pensar melhor nas abstrações.
- Evitam acoplamentos desnecessários.
- Promovem código expressivo, testável e sustentável.