Em 2008, A ThoughtWorks lançou um livro com diversos artigos de desenvolvedores da empresa.
Um desses artigos foi o "Object Calisthenics" por Jeff Bay, um desenvolvedor Java.
Um nível de identação por método
Não usar o "else"
Encapsular todos os tipos primitivos e strings
Encapsular suas coleções em uma classe
Um ponto por linha
Não abreviar
Manter suas entidades pequenas
Nenhuma classe com mais de 2 variáveis com instância
Nenhum getter/setter/property
Se você precisa de mais um nível, você deve criar outro método e chama-lo
class Board {
String board() {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
buf.append(data[i][j]);
}
buf.append(“\n”);
}
return buf.toString();
}
}
class Board {
String board() {
StringBuffer buf = new StringBuffer();
collectRows(buf);
return buf.toString();
}
void collectRows(StringBuffer buf) {
for (int i = 0; i < 10; i++) {
collectRow(buf, i);
}
}
void collectRow(StringBuffer buf, int row) {
for (int i = 0; i < 10; i++) {
Buf.append(data[row][i]);
}
buf.append(“\n”);
}
}
Ao invéz de usar o "else", saia do método caso entre no if.
function isValid(user) {
if (user.name.length > 5 && user.age >= 18) {
return true
} else {
return false
}
}
function isValid(user) {
if (user.name.length <= 5) {
return false
}
if (user.age < 18) {
return false
}
return true
}
Aponta para o bad smell "Primitive Obsession", que acontece quando você usa tipos de dados para representar idéias do domínio da aplicação.
var regex = new RegExp('^[a-z ]+$', 'gi')
function Name(value) {
this.value = value
}
Name.prototype.isValid = function() {
return regex.test(this.value)
}
Toda coleção deve ser encapsulada em sua própria classe, junto com os seus comportamentos.
function Members(members) {
this.members = members || []
}
Members.prototype.add(member) {
this.members.push(member)
}
Members.prototype.isValid() {
var isValid = true
this.members.forEach(function(member) {
if (!member.isValid()) {
isValid = false
return
}
})
return isValid
}
"lei de demeter": Você só poder acessar objetos ligados diretamente a você.
Seller.prototype.sell = function(client, cart) {
// Chamar o método getMoney() é uma violação dessa regra
if (client.getWallet().getMoney() >= cart.getTotal()) {
}
// Ao invéz disso, deveríamos chamar algo do tipo:
if (client.hasEnoughMoney(cart.getTotal())) {
}
}
Abreviações são confusas e podem esconder um problema de design da aplicação.
Nenhuma classe com mais de 50 linhas e nenhum pacote com mais de 10 arquivos.
Quanto mais variáveis com instâncias, menor a coesão da classe.
Se você tiver mais que isso, quebre seu código em outras classes.
Baseado no princípio, "Tell, don't ask".
// Validate person
// WRONG
var regex = new RegExp('^[a-z ]+$', 'gi')
if (regex.test(person.getName())) {
// ...
}
// OK
if (person.isValid()) {
// ...
}