Object CalisthenicsDefiniçãoAs 9 regras do Object Calisthenics:Objetivo: Quando usar?Videos YouTubeReferênciasOrigem e Referências PrincipaisOnde Encontrar?Comparação com Outras MetodologiasReferência Primária (Origem do Conceito)Referências Secundárias (Influências e Contexto)ObservaçõesAplicando em Python1. Clean Code & Boas Práticas em PythonLivro mais referenciado (Clean Code - Robert C. Martin)Adaptação para PythonLivro específico para Python2. Object Calisthenics & Design Orientado a Objetos em PythonOrigem do Object CalisthenicsAplicação Prática em PythonLivro Avançado (Python OO)3. Artigos Acadêmicos Complementares4. Outras Referências?ExemploCenário: Validar acesso de usuárioVersão Inicial (Com else
)Versão Refatorada (Sem else
)Opção 1: Early ReturnsOpção 2: Lógica Booleana ExplícitaExemplo Completo em PythonPor Que Evitar else
?Outras Técnicas para Eliminar else
**Aplicando em C++1. Referências para Clean Code em C++Livros Clássicos1. "Clean Code: A Handbook of Agile Software Craftsmanship"2. "Clean C++: Sustainable Software Development Patterns and Best Practices"3. "Effective C++: 55 Specific Ways to Improve Your Programs and Designs"2. Referências para Object Calisthenics em C++Origem do ConceitoAplicação em C++Artigo: "Object Calisthenics Applied to C++"Discussão no Stack Overflow3. Artigos Acadêmicos e Guias Práticos1. "Modern C++ Best Practices" (Microsoft Docs)2. "C++ Core Guidelines" (Bjarne Stroustrup & Herb Sutter)3. "SOLID Principles in C++" (Artigo Medium)4. Exemplo Prático (C++ com Object Calisthenics)Regra: "No else
"AntesDepois (Sem else
)5. Ferramentas para Aplicar Clean Code em C++ResumoAplicações em Sistemas Embarcados1. Princípios Adaptados para EmbarcadosA. Clean Code em Embarcados (C/C++)B. Object Calisthenics Adaptado2. Referências para EmbarcadosLivrosArtigos e Guias Online3. Exemplo Prático (C para Embarcados)Antes (Código Não Otimizado)Depois (Clean Code + Embarcados)4. Ferramentas para EmbarcadosResumoExemplo de máquina de estados sem else
Cenário: Controlador de Motor DC com 3 EstadosVersão Ruim (Com if/else
Aninhados)Versão Refatorada (Máquina de Estados sem else
)Passo 1: Definir os EstadosPasso 2: Implementar Transições sem else
Versão com Table-Driven FSM (Avançado)Quando Usar?Referências Exemplo no Mundo RealExemplo para STM32Hardware Utilizado1. Definindo os Estados e Hardware (CubeMX)Configuração do PWM (CubeMX)Código: Estados e Inicialização2. Máquina de Estados sem else
Implementação da FSM3. Loop Principal (main.c)4. Explicação das Melhorias5. Teste no Hardware RealReferências para STM32Próximos Passos ?
Object Calisthenics é um conjunto de 9 práticas ou regras para melhorar o design de código orientado a objetos (OO), proposto por Jeff Bay no livro The ThoughtWorks Anthology. O objetivo é exercitar boas práticas de programação, tornando o código mais legível, maintainable e extensível através de restrições deliberadas que forçam o uso eficiente de OO.
Apenas um nível de indentação por método
if
dentro de if
). Não use a palavra-chave else
else
por estruturas como early returns ou polimorfismo. return
antecipado ou Strategy Pattern.Envolva todos os tipos primitivos e strings
int
, string
) para representar conceitos de domínio. Cpf
em vez de usar string cpf
.Coleções como first-class citizens
class Pedido { List<Item> itens; }
→ class ItensPedido { ... }
.Apenas um ponto (.
) por linha (Lei de Demeter)
obj.getA().getB().doSomething()
. Não abrevie nomes
Cliente
em vez de Cli
) melhoram a legibilidade. Mantenha entidades pequenas
Nenhuma classe com mais de duas variáveis de instância
Point(x, y)
).Não use getters/setters (ou propriedades públicas)
cliente.efetuarPagamento()
em vez de cliente.setSaldo(...)
.Essas regras forçam você a pensar em design orientado a objetos puro, evitando vícios de código procedural (como classes "God Objects") e promovendo:
Você já aplicou alguma dessas regras intuitivamente? Alguma delas parece especialmente útil (ou controversa)?
A metodologia Object Calisthenics foi proposta originalmente por Jeff Bay em um capítulo do livro "The ThoughtWorks Anthology: Essays on Software Technology and Innovation" (2008), publicado pela editora Pragmatic Bookshelf. Esse livro é uma coletânea de artigos escritos por profissionais da ThoughtWorks, uma consultoria de software conhecida por promover boas práticas de engenharia de software.
Fonte Original:
Contexto e Influências:
Disseminação:
Livro The ThoughtWorks Anthology (2008):
Discussões derivadas:
Se quiser explorar mais, recomendo o livro original ou materiais sobre refatoração (Martin Fowler) e design OO. Você já teve contato com algum desses autores?
Aqui está a referência formal no estilo Harvard, incluindo links disponíveis para as fontes principais relacionadas ao Object Calisthenics:
Bay, J. (2008) Object Calisthenics. In: The ThoughtWorks Anthology: Essays on Software Technology and Innovation. 1st ed. Raleigh, NC: Pragmatic Bookshelf, pp. 117–136.
Martin, R.C. (2000) Design Principles and Design Patterns. [Online]
Fowler, M. (1999) Refactoring: Improving the Design of Existing Code. 1st ed. Boston: Addison-Wesley.
Evans, E. (2003) Domain-Driven Design: Tackling Complexity in the Heart of Software. 1st ed. Boston: Addison-Wesley.
Aqui estão as referências mais contundentes e amplamente citadas para guiar a produção de código em Python usando Clean Code e Object Calisthenics, incluindo livros clássicos, artigos influentes e materiais específicos para Python:
Martin, R.C. (2008) Clean Code: A Handbook of Agile Software Craftsmanship. 1st ed. Upper Saddle River, NJ: Prentice Hall.
ISBN: 978-0132350884
Por que é relevante?
Van Rossum, G., Warsaw, B. & Coghlan, N. (2001) PEP 8 -- Style Guide for Python Code. [Online] Python Software Foundation.
Link: PEP 8
Por que é relevante?
Meier, K. (2023) Clean Code in Python: Develop maintainable and efficient code. 2nd ed. Birmingham: Packt Publishing.
ISBN: 978-1800560215
Por que é relevante?
Bay, J. (2008) Object Calisthenics. In: The ThoughtWorks Anthology. 1st ed. Raleigh, NC: Pragmatic Bookshelf, pp. 117–136.
Link: Livro (PragProg)
Por que é relevante?
else
, classes pequenas). Artigo: "Python and the Principles of Object-Oriented Design" (2020) por Brandon Rhodes.
Link: PyOhio Talk (vídeo) + Slides
Por que é relevante?
Lott, S.F. (2019) Python Object-Oriented Programming. 4th ed. Birmingham: Packt Publishing.
ISBN: 978-1789615852
Por que é relevante?
"How to Write Clean Code?" (2019) – Uma revisão sistemática de boas práticas.
"Pythonic Code Review" (2021) – Critérios para código limpo em Python.
Aqui está um exemplo prático em Python aplicando a regra "No else
" do Object Calisthenics, com comparação entre o código antes e depois da refatoração:
Suponha que precisamos verificar se um usuário tem permissão para acessar um recurso, com duas condições:
else
)xxxxxxxxxx
def check_access(user):
if user.is_logged_in:
if user.is_admin or user.age >= 18:
return True
else:
return False
else:
return False
Problemas:
if/else
. else
)Regra aplicada: Substituir else
por early returns ou lógica booleana.
xxxxxxxxxx
def check_access(user):
if not user.is_logged_in:
return False
return user.is_admin or user.age >= 18
Melhorias:
else
. xxxxxxxxxx
def check_access(user):
return user.is_logged_in and (user.is_admin or user.age >= 18)
Melhorias:
xxxxxxxxxx
class User:
def __init__(self, is_logged_in, is_admin, age):
self.is_logged_in = is_logged_in
self.is_admin = is_admin
self.age = age
# Teste
user1 = User(is_logged_in=True, is_admin=False, age=20)
user2 = User(is_logged_in=True, is_admin=False, age=15)
print(check_access(user1)) # True (idade >= 18)
print(check_access(user2)) # False
else
?else
**Quer ver um exemplo com polimorfismo ou outra técnica? Posso adaptar!
Os princípios de Clean Code e Object Calisthenics são totalmente aplicáveis em C++ e podem melhorar significativamente a qualidade do seu código. Abaixo estão as melhores referências (livros, artigos e páginas web) para guiar essa prática em C++:
Autor: Robert C. Martin ("Uncle Bob")
Ano: 2008
ISBN: 978-0132350884
Relevância:
Autor: Stephan Roth
Ano: 2017
ISBN: 978-1484233651
Relevância:
Autor: Scott Meyers
Ano: 2005 (3ª ed.)
ISBN: 978-0321334879
Relevância:
Capítulo "Object Calisthenics"
else
"xxxxxxxxxx
bool checkAccess(const User& user) {
if (user.isLoggedIn()) {
if (user.isAdmin() || user.getAge() >= 18) {
return true;
} else {
return false;
}
} else {
return false;
}
}
else
)xxxxxxxxxx
bool checkAccess(const User& user) {
if (!user.isLoggedIn()) {
return false;
}
return user.isAdmin() || user.getAge() >= 18;
}
Melhorias:
else
com early return. Clang-Tidy: Analisa código C++ seguindo boas práticas.
Cppcheck: Verificador estático para C++.
Os princípios de Clean Code e Object Calisthenics podem ser aplicados em C/C++ para sistemas embarcados, mas com adaptações devido às restrições de RAM, processamento e armazenamento. Abaixo, listo as referências mais citadas e como adaptar essas práticas para ambientes de baixo recurso.
Funções pequenas e legíveis
Mantenha funções curtas (< 20 linhas) para facilitar depuração em sistemas limitados.
Exemplo:
xxxxxxxxxx
// Ruim (função longa)
void processSensorData() { /* 100+ linhas */ }
// Bom (dividido)
void readSensor() { /* ... */ }
void filterData() { /* ... */ }
void sendToCAN() { /* ... */ }
Evite alocação dinâmica
Macros vs. Funções inline
inline
ou macros para otimização, mas sem sacrificar legibilidade. Regra: "Nenhuma classe com >2 variáveis de instância"
structs
pequenas (ex: struct Sensor { int value; bool valid; }
). Regra: "Não use else
"
switch-case
). Regra: "Encapsule primitivos"
typedef
para dar semântica (ex: typedef uint32_t speed_mps_t
). "Test-Driven Development for Embedded C" (James W. Grenning, 2011)
"Embedded C Coding Standard" (Barr Group, 2018)
"Making Embedded Systems" (Elecia White, 2011)
NASA C Coding Standard
MISRA C/C++ (Padrão industrial para segurança crítica)
goto
). "Embedded Systems Best Practices" (ARM Developer)
xxxxxxxxxx
// Função confusa e alocação dinâmica
float* readSensors(int* count) {
float* data = malloc(10 * sizeof(float));
// Lógica complexa aqui...
return data; // Risco de vazamento!
}
xxxxxxxxxx
// Buffer estático (sem malloc)
float sensorData[MAX_SENSORS];
// Função pequena e previsível
bool readSensors(float* output, int max_size) {
if (max_size < MAX_SENSORS) return false;
for (int i = 0; i < MAX_SENSORS; i++) {
output[i] = readADC(i); // Exemplo simples
}
return true;
}
Melhorias:
Cppcheck
PVS-Studio
FreeRTOS Best Practices
Clean Code e Object Calisthenics são viáveis em embarcados, mas com ajustes:
Referências-chave:
else
Segue um exemplo prático de máquina de estados (FSM - Finite State Machine) em C para sistemas embarcados, substituindo condicionais aninhadas (if/else
ou switch-case
) por uma implementação mais limpa e eficiente, seguindo os princípios de Clean Code e Object Calisthenics:
IDLE
: Motor parado. ACCELERATING
: Motor acelerando até a velocidade desejada. RUNNING
: Motor em velocidade constante. if/else
Aninhados)xxxxxxxxxx
// Código confuso e difícil de manter
void updateMotorState(int speed, bool isEnabled) {
if (isEnabled) {
if (speed < TARGET_SPEED) {
printf("Acelerando...\n");
setPWM(speed + 1);
} else {
printf("Velocidade constante.\n");
setPWM(TARGET_SPEED);
}
} else {
printf("Motor desligado.\n");
setPWM(0);
}
}
Problemas:
else
)xxxxxxxxxx
typedef enum {
STATE_IDLE,
STATE_ACCELERATING,
STATE_RUNNING
} MotorState;
static MotorState currentState = STATE_IDLE;
else
xxxxxxxxxx
void updateMotorState(int speed, bool isEnabled) {
switch (currentState) {
case STATE_IDLE:
if (isEnabled) {
currentState = STATE_ACCELERATING;
printf("Iniciando aceleração.\n");
}
break;
case STATE_ACCELERATING:
if (!isEnabled) {
currentState = STATE_IDLE;
printf("Parando motor.\n");
} else if (speed >= TARGET_SPEED) {
currentState = STATE_RUNNING;
printf("Velocidade alcançada.\n");
} else {
setPWM(speed + 1);
}
break;
case STATE_RUNNING:
if (!isEnabled) {
currentState = STATE_IDLE;
printf("Parando motor.\n");
} else {
setPWM(TARGET_SPEED);
}
break;
}
}
Vantagens:
else
desnecessários. STATE_ERROR
). Para sistemas mais complexos, use uma tabela de transições:
xxxxxxxxxx
typedef void (*StateHandler)(int, bool);
typedef struct {
MotorState state;
StateHandler handler;
} StateTransition;
// Handlers para cada estado
void handleIdle(int speed, bool isEnabled) {
if (isEnabled) currentState = STATE_ACCELERATING;
}
void handleAccelerating(int speed, bool isEnabled) {
if (!isEnabled) currentState = STATE_IDLE;
else if (speed >= TARGET_SPEED) currentState = STATE_RUNNING;
else setPWM(speed + 1);
}
// Tabela de transições
StateTransition transitions[] = {
{STATE_IDLE, handleIdle},
{STATE_ACCELERATING, handleAccelerating},
// ...
};
void updateMotorState(int speed, bool isEnabled) {
for (int i = 0; i < sizeof(transitions)/sizeof(transitions[0]); i++) {
if (transitions[i].state == currentState) {
transitions[i].handler(speed, isEnabled);
break;
}
}
}
Vantagens:
Para Máquinas de Estados em Embarcados:
"Practical Statecharts in C/C++" (Miro Samek, 2002)
Artigo: "State Machines for Event-Driven Systems" (Embedded.com)
MISRA C Guidelines (Regra 15.1: Evite switch
aninhados)
IDLE
, BRAKING
, PUMPING
. INIT
, READING
, ERROR
. Segue um exemplo com hardware real (ex: STM32 + PWM)...
Aqui está um exemplo completo de máquina de estados (FSM) para controlar um motor DC com PWM em uma placa STM32 (usando HAL e CubeMX), seguindo princípios de Clean Code e sem else
desnecessários:
Placa: STM32F4 Discovery (ou qualquer STM32 com timer PWM).
Periféricos:
Abra o CubeMX e selecione um timer (ex: TIM3).
Ative um canal PWM (ex: TIM3_CH1 em PB4).
Configure:
xxxxxxxxxx
// --- states.h ---
typedef enum {
STATE_IDLE,
STATE_ACCELERATING,
STATE_RUNNING
} MotorState;
// Protótipos
void FSM_Init(void);
void FSM_Update(void);
// --- main.c ---
// Variáveis globais
MotorState currentState = STATE_IDLE;
TIM_HandleTypeDef htim3; // Timer do PWM
uint16_t currentSpeed = 0;
const uint16_t TARGET_SPEED = 900; // Valor PWM máximo (ex: 90% duty cycle)
// Handler do botão (interrupção ou polling)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_13) {
currentState = (currentState == STATE_IDLE) ? STATE_ACCELERATING : STATE_IDLE;
}
}
else
xxxxxxxxxx
// --- states.c ---
void FSM_Init(void) {
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // Inicia PWM
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); // Duty cycle = 0%
}
void FSM_Update(void) {
switch (currentState) {
case STATE_IDLE:
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0); // Motor desligado
break;
case STATE_ACCELERATING:
currentSpeed += 10;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, currentSpeed);
if (currentSpeed >= TARGET_SPEED) {
currentState = STATE_RUNNING;
}
break;
case STATE_RUNNING:
// Mantém a velocidade constante
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, TARGET_SPEED);
break;
}
}
xxxxxxxxxx
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init(); // Configura PWM via CubeMX
FSM_Init();
while (1) {
FSM_Update();
HAL_Delay(100); // Atualiza a cada 100ms
}
}
Sem else
:
if
dos estados. STATE_ACCELERATING
, a mudança para STATE_RUNNING
ocorre sem else
. Baixo Acoplamento:
Eficiência em Embarcados:
Conecte um motor DC ao PB4 (saída PWM) e um botão em PC13.
Ao pressionar o botão:
IDLE
. Livro: "Mastering STM32" (Carmine Noviello):
A step-by-step guide to the most complete ARM Cortex-M platform, using the official STM32Cube development environment.
Fernando Passold, 02/05/2025