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):

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. Não abreviar nomes (“Don’t abbreviate”) — favorece nomes claros, compreensíveis, não abreviações obscuras. DEV Community
  7. Mantenha todas as entidades pequenas (“Keep all entities small”) — classes/metódos não devem ser grandes com muitas responsabilidades. William Durand
  8. 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
  9. 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

  1. Comece com 1 ou 2 regras — não tente aplicar todas de uma vez.
  2. Promova code reviews voltados a práticas de design.
  3. Documente exceções (quando quebrar uma regra, justifique).
  4. Use como exercício em Dojos e Pair Programming.
  5. Reforce a ideia de que código é comunicação, não apenas execução.
  6. 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”.
  7. Promova um workshop interno para apresentar as regras e discutir como se aplicam no código atual.
  8. Defina checkpoints em code reviews para verificar aderência às regras selecionadas.
  9. Documente exceções, por que se foge de uma regra em determinado caso, qual o trade-off.
  10. Meça o impacto qualitativo: é mais fácil ler, modificar, testar o código?
  11. 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.