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 elseCená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 elseVersã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 elseImplementaçã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)xxxxxxxxxxdef check_access(user): if user.is_logged_in: if user.is_admin or user.age >= 18: return True else: return False else: return FalseProblemas:
if/else. else)Regra aplicada: Substituir else por early returns ou lógica booleana.
xxxxxxxxxxdef check_access(user): if not user.is_logged_in: return False return user.is_admin or user.age >= 18Melhorias:
else. xxxxxxxxxxdef check_access(user): return user.is_logged_in and (user.is_admin or user.age >= 18)Melhorias:
xxxxxxxxxxclass 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# Testeuser1 = 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)) # Falseelse?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"xxxxxxxxxxbool checkAccess(const User& user) { if (user.isLoggedIn()) { if (user.isAdmin() || user.getAge() >= 18) { return true; } else { return false; } } else { return false; }}else)xxxxxxxxxxbool 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âmicafloat* 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ívelbool 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:
elseSegue 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 mantervoid 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)xxxxxxxxxxtypedef enum { STATE_IDLE, STATE_ACCELERATING, STATE_RUNNING} MotorState;static MotorState currentState = STATE_IDLE;elsexxxxxxxxxxvoid 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:
xxxxxxxxxxtypedef void (*StateHandler)(int, bool);typedef struct { MotorState state; StateHandler handler;} StateTransition;// Handlers para cada estadovoid 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çõesStateTransition 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ótiposvoid FSM_Init(void);void FSM_Update(void);// --- main.c ---// Variáveis globaisMotorState currentState = STATE_IDLE;TIM_HandleTypeDef htim3; // Timer do PWMuint16_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; }}elsexxxxxxxxxx// --- 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; }}xxxxxxxxxxint 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