Bom, este post foi inspirado por um aluno do curso que eu ministrei fim de semana passado em Pato Branco/PR, mas este post não é culpa só dele
O post é inspirado em coisas que eu já vi e já fiz muito por ai …
A idéia básica deste post é que:
Qualquer um pode escrever código que um computador entende, mas apenas um programador muito bom, escreve código que uma pessoa entende.
Como premissa básica, se você programa em uma linguagem, siga os padrões dela, por exemplo:
E assim por diante, ou seja, siga os padrões básicos da linguagem que estiver trabalhando.
Alem dos padrões das linguagens, cada empresa normalmente possui um padrão de formatação, por tanto, siga o padrão da empresa, e de preferência, configure a sua IDE para te ajudar neste trabalho.
Refactoring é seu amigo!
Refatore sempre que precisar para melhorar a legibilidade do código, ou quando perceber que alguma coisa esta implementada no lugar errado.
A boa noticia é que a maioria das IDEs, para diversas linguagens, tem suporte para diversos tipos refactoring.
A má noticia é que se a sua IDE ou linguagem, não tem suporte a refatoring, ou não tem suporte ao refactoring que você precisa, você vai ter que faze-lo manualmente.
DRY (Don’t Repeat Yourself)
Não se repita, se você escreveu alguma coisa em algum lugar, reuse, não escreva novamente!
Mas preste atenção, reuso não é igual a copiar e colar, se você precisar copiar e colar, é por que provavelmente fez errado da primeira vez.
Considere este exemplo (Retirado do livro encontrado aqui)
public class BookRental {
String id;
String customerName;
...
}
public class BookRentals {
private Vector rentals;
public String getCustomerName(String rentalId) {
for (int i = 0; i < rentals.size(); i++) {
BookRental rental = (BookRental) rentals.elementAt(i);
if (rental.getId().equals(rentalId)) {
return rental.getCustomerName();
}
}
throw new RentalNotFoundException();
}
}
public class RentalNotFoundException extends Exception {
...
}
Agora imagine que você precisa adicionar um método para remover um aluguel pelo ID:
public class BookRentals {
private Vector rentals;
public String getCustomerName(String rentalId) {
for (int i = 0; i < rentals.size(); i++) {
BookRental rental = (BookRental) rentals.elementAt(i);
if (rental.getId().equals(rentalId)) {
return rental.getCustomerName();
}
}
throw new RentalNotFoundException();
}
public void deleteRental(String rentalId) {
for (int i = 0; i < rentals.size(); i++) {
BookRental rental = (BookRental) rentals.elementAt(i);
if (rental.getId().equals(rentalId)) {
rentals.remove(i);
return;
}
} throw new RentalNotFoundException();
}
}
Você acha que este código esta OK? lembra-se do DRY? neste exemplo simples ja temos muito código duplicado, o que com certeza não é bom, então, podemos fazer o seguinte refactoring:
public class BookRentals {
private Vector rentals;
public String getCustomerName(String rentalId) {
int rentalIdx = getRentalIdxById(rentalId);
return ((BookRental) rentals.elementAt(rentalIdx)).getCustomerName();
}
public void deleteRental(String rentalId) {
rentals.remove(getRentalIdxById(rentalId));
} private int getRentalIdxById(String rentalId) {
for (int i = 0; i < rentals.size(); i++) {
BookRental rental = (BookRental) rentals.elementAt(i);
if (rental.getId().equals(rentalId)) {
return i;
}
}
throw new RentalNotFoundException();
}
}
Por que remover código duplicado?
Em geral, se um código esta duplicado em 10 lugares, se você precisar alterar este código precisara lembrar de todos os 10 lugares, o qe provavelmente não vai acontecer, por tanto vai criar bugs no sistema.
O seu código não precisa de comentários! des de que ele seja legivel!
Considere este outro exemplo do mesmo livro, em que é desenvolvida uma aplicação para gerenciamento de conferencias, e que existe uma barra lateral onde devem ser exibidas informações sobre o participante:
//It stores the information of a participant to be printed on his badge.
public class Badge {
String pid; //participant ID
String engName; //participant's full name in English
String chiName; //participant's full name in Chinese
String engOrgName; //name of the participant's organization in English
String chiOrgName; //name of the participant's organization in Chinese
String engCountry; //the organization's country in English
String chiCountry; //the organization's country in Chinese
//***********************
//constructor.
//The participant ID is provided. It then loads all the info from the DB.
//***********************
Badge(String pid) {
this.pid = pid;
//***********************
//get the participant's full names.
//***********************
ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
Participant part = partsInDB.locateParticipant(pid);
if (part != null) {
//get the participant's full name in English.
engName = part.getELastName() + ", " + part.getEFirstName();
//get the participant's full name in Chinese.
chiName = part.getCLastName()+part.getCFirstName();
//***********************
//get the organization's name and country.
//***********************
OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
//find the ID of the organization employing this participant.
String oid = orgsInDB.getOrganization(pid);
if (oid != null) {
Organization org = orgsInDB.locateOrganization(oid);
engOrgName = org.getEName();
chiOrgName = org.getCName();
engCountry = org.getEAddress().getCountry();
chiCountry = org.getCAddress().getCountry();
}
}
}
...
}
Agora transforme os comentários em código, fazendo-o tão simples quanto os comentários.
//It stores the information of a participant to be printed on his badge.
public class Badge {
...
}
Para que precisamos deste comentário se podemos escrever assim:
public class ParticipantInfoOnBadge {
...
}
E nesta parte:
public class ParticipantInfoOnBadge {
String pid; //participant ID
String engName; //participant's full name in English
String chiName; //participant's full name in Chinese
String engOrgName; //name of the participant's organization in English
String chiOrgName; //name of the participant's organization in Chinese
String engCountry; //the organization's country in English
String chiCountry; //the organization's country in Chinese
...
}
Por que não transformas os comentários em variáveis assim:
public class ParticipantInfoOnBadge {
String participantId;
String participantEngFullName;
String participantChiFullName;
String engOrgName;
String chiOrgName;
String engOrgCountry;
String chiOrgCountry;
...
}
Ou destes comentários?
public class ParticipantInfoOnBadge {
...
//***********************
//constructor.
//The participant ID is provided. It then loads all the info from the DB.
//***********************
ParticipantInfoOnBadge(String pid) {
this.pid = pid;
...
}
}
Se podemos transforma-los em nomes de parametros:
public class ParticipantInfoOnBadge {
...
//***********************
//constructor.
//It loads all the info from the DB.
//***********************
ParticipantInfoOnBadge(String participantId) {
this.participantId = participantId;
...
}
}
Podemos tambem transformar comentários em partes do código do método:
public class ParticipantInfoOnBadge {
...
//***********************
//constructor.
//***********************
ParticipantInfoOnBadge(String participantId) {
loadInfoFromDB(participantId);
} void loadInfoFromDB(String participantId) {
this.participantId = participantId;
...
}
}
Agora pegue este outro fragmento de código:
void loadInfoFromDB(String participantId) {
this.participantId = participantId;
//***********************
//get the participant's full names.
//***********************
ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
Extract some code to form a method and use the comment to name the method 41
Licensed for viewing only. Printing is prohibited. For hard copies, please purchase from www.agileskills.org
Participant part = partsInDB.locateParticipant(participantId);
if (part != null) {
//get the participant's full name in English.
engFullName = part.getELastName() + ", " + part.getEFirstName();
//get the participant's full name in Chinese.
chiFullName = part.getCLastName()+part.getCFirstName();
//***********************
//get the organization's name and country.
//***********************
OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
//find the ID of the organization employing this participant.
String oid = orgsInDB.getOrganization(participantId);
if (oid != null) {
Organization org = orgsInDB.locateOrganization(oid);
engOrgName = org.getEName();
chiOrgName = org.getCName();
engOrgCountry = org.getEAddress().getCountry();
chiOrgCountry = org.getCAddress().getCountry();
}
}
}
E me diga por que não transformas os comentários em nomes de métodos assim:
void loadInfoFromDB(String participantId) {
this.participantId = participantId;
getParticipantFullNames();
//***********************
//get the organization's name and country.
//***********************
//find the ID of the organization employing this participant.
OrganizationsInDB orgsInDB = OrganizationsInDB.getInstance();
String oid = orgsInDB.getOrganization(participantId);
if (oid != null) {
Organization org = orgsInDB.locateOrganization(oid);
engOrgName = org.getEName();
chiOrgName = org.getCName();
engOrgCountry = org.getEAddress().getCountry();
chiOrgCountry = org.getCAddress().getCountry();
}
} void getParticipantFullNames() {
ParticipantsInDB partsInDB = ParticipantsInDB.getInstance();
Participant part = partsInDB.locateParticipant(participantId);
if (part != null) {
//get the participant's full name in English.
engFullName = part.getELastName() + ", " + part.getEFirstName();
//get the participant's full name in Chinese.
chiFullName = part.getCLastName()+part.getCFirstName();
}
}
E assim por diante, seguindo algumas regras básicas, o código vai ser bastante legível, dispensando boa parte dos comentários, o que vai fazer com que o seu desenvolvimento seja mais rápido, e vai também fazer com que outras pessoas consigam ler o seu código sem problemas.
Mas eu não estou dizendo que não é para comentar nada, mas com certeza, boa parte os comentários é dispensavel, se o seu código for legível!
Bom, acho que é isto por enquanto …
Por favor, contribua sua ideia para melhorar este manifesto, e se gostou dele,divulge-o, isto ainda vai lhe poupar muito tempo!
<MODO SARCASMO ON>
Apenas para deixar claro, a maior parte das regras definidas neste post, esta acima de qualquer contestação, e é por definição, verdade absoluta. (Ou seja, até que se prove ao contrário, estas regras estão acima de contestação).
</MODO SARCASMO ON>
If you enjoyed this post, make sure you subscribe to my RSS feed!Tags: Trabalho
Se antes disseste que não fazia sentido ter um atributo clientId numa classe Cliente, podendo só utilizar id, o mesmo vale para a possivel classe ParticipantInfoOnBadge, que não deveria ter um participantId.
eu até concordo, se o nome do campo fosse ID, mas participantID é muito melhor do que pid …
Mas ainda tem outra coisa, o nome da classe é: ParticipantInfoOnBadge
se ela tiver um atributo “id” ele é o ID do Participant? ou o ID do conjunto ParticipantInfo? ou o ID do ParticipantInfoOnBadge?
se a classe fosse Participant concordo que o nome do atributo deveria ser “id” e não participantID, mas como o nome da classe não é Participant e sim ParticipantInfoOnBadge é necessário informar de quem é o ID em questão …
Caso contrario em vez de ficar mais claro o código, ele ficaria mais ambíguo.
por tanto um Participant não tem participantID e sim “id” mas um ParticipantInfo ou um ParticinaptInfoOnBadge podem ter um participantID …
não sei se fui claro …
Concordo veementemente com o post, salvo a última parte. Se não é possível contestar algo, como melhorar? Como falar que existe um mísero problema em uma dessas regras que se modificado melhoraria consideravelmente a regra? E quando chegar o momento de tornar a regra obsoleta? E, brincando um pouco com as palavras escolhidas na última frase, como eu vou provar o contrário, que essas regras podem ser contestadas, se para tal terei que constestá-las em primeiro lugar? Considerar algo como inconstetável sempre foi sinônimo de problemas. Por isso, se me permite uma humilde sugestão, seria interressante remover o último paragráfo como um todo.
Verdades absolutas são a raiz de todo mal.
Sim, verdades absolutas são a raiz de todo o mal, mas eu achei que o até que se prove o contrario tinha deixado claro o sarcasmo na frase anterior
mas beleza, ja que o sarcasmo não ficou tão claro quando eu achei que tinha ficado, eu removo a ultima frase …
Com a adição dessas tags de sacarsmo, o texto ficou perfeito, concordo com tudo.
Como dica para os iniciantes, eu sugiro ler o link abaixo sobre as conveções de códido que a Sun publicou vários anos atrás. Eu utilizei o Checkstyle junto com o Eclipse para que eu me adequasse às regras apresentadas ali.
http://java.sun.com/docs/codeconv/
ParticipantId? Isso tem cheiro de modelo relacional vazando para o de objetos. Que tal ter referências entre objetos e não chaves estrangeiras?