Robert C. Martin aka Uncle Bob
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
Martin Fowler
"Mal nommer les choses, c'est ajouter au malheur du monde !"
Albert Camus
"There are only two hard things in Computer Science:
- cache invalidation,
- naming things" Phil Karlton
Vous allez passer beaucoup plus de temps à relire du code qu'à en écrire.
public List<int[]> getFlg() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList ) {
if (x[0] == 4)
list1.add(x);
}
return list1;
}
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard ) {
if (cell.isFlagged())
flaggedCells.add(cell);
}
return flaggedCells;
}
Parlez au business !
en théorie, un PO ou un utilisateur devrait pouvoir lire votre code.
Ou au moins les tests et titres de fonctions.
Bonus : en parlant au business, vous comprendrez vraiment le problème métier.
Evitez les x, i, j, temp
Evitez les List, array, les prefixes de types (u8_price)
Evitez le vocabulaire technique, préferez le vocabulaire métier.
Class : Nom
Methode : verbe d'action
1 seul niveau d'abstraction
taille de la main ?
pas plus d'un if / for ?
public RGBColor readCurrentColor(BlinkLed led) {
device.sendCommand(new ReadColorRequest(led));
byte[] response = device.readResponse();
int red = response[2] >= 0 ? response[2] : response[2] + 256;
int green = response[3] >= 0 ? response[3] : response[3] + 256;
int blue = response[4] >= 0 ? response[4] : response[4] + 256;
return new RGBColor(red, green, blue);
}
public RGBColor readCurrentColor(BlinkLed led) {
device.sendCommand(new ReadColorRequest(led));
byte[] response = device.readResponse();
return extractColor(response);
}
private RGBColor extractColor(byte[] response) {
int red = convertToPositiveInt(response[2]);
int green = convertToPositiveInt(response[3]);
int blue = convertToPositiveInt(response[4]);
return new RGBColor(red, green, blue);
}
private int convertToPositiveInt(byte byt) {
return byt >= 0 ? byt : byt + 256;
}
Extract Method
mais pas les deux !
/*
* A comment to please checkstyle
*/
/*
* Set the port
*
* @params port
*/
public void setPort(Port port) {this.port=port}
...
} /* end for */
dao.flush();
default :
break;
} /* end switch */
} /* end if */
} /* end if */
} catch ...
Exceptions:
Don’t use a comment when you can use a function or a variable
Expose comment on l'utilise, le métier
pas l'implémentation spécifique
Penser au TDD
Pas bien !
a.getB().getC().doThings();
Bien !
a.doThings();
Un module n'a pas à connaitre l'implémentation des objets qu'il manipule.
A class should have one and only one reason to change, meaning that a class should have only one job.
Evitez les Managers
Un manager fait un peu de tout mais mal, beaucoup de rien et embrouille tout le monde.
Objects or entities should be open for extension, but closed for modification.
Penser héritage
public Money calculatePay(Employee e) {
switch (e.type) {
case COMMISSIONED:
return calculateCommissionedPay(e);
case HOURLY:
return calculateHourlyPay(e);
case SALARIED:
return calculateSalariedPay(e);
default:
throw new InvalidEmployeeType(e.type);
}
}
Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.
objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.
A client should never be forced to implement an interface that it doesn't use or clients shouldn't be forced to depend on methods they do not use.
one should "depend upon abstractions, [not] concretions."
A. High level modules should not depend upon low level modules. Both should depend upon abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions.
Pas bien !
public class Client {
private Service service;
public Client() {
this.service = new ServiceLieAUneDatabasePrecise();
}
public String greet() {
return "Hello " + service.getName();
}
}
Bien !
public class Client {
private Service service;
public Client(Service service) {
this.service = service;
}
...
}
Des frameworks permettent de faire "facilement" de l'injection de dépendances.
A voir si la complexité et les contraintes qu'ils apportent sont compensés.
Ne jamais coupler avec des librairies externes !
Jamais
Toujours utiliser des abstractions et des façades
Ne retournez jamais null.
Soit le vide est une valeur possible et c'est un objet spécifique
("", un UserEmpty, emptylist ...)
Soit c'est une erreur et exception