Arnaud Labourel
21 octobre 2019
“Mal nommer un objet, c’est ajouter au malheur de ce monde”
La L3 info : MIAGE ne dépend pas de la même UFR que la L2 info : MI, elle dépend de la FEG et non de la FS. Pour faire vos IA et IP, vous devez donc contacter la scol de Forbin et non celle de SCH.
i
, j
, …a1
, a2
, a3
, …rec
, res
, …temporary
, result
, …accountList
doit être une List
(et pas un array
ou un autre type)persons
et non person
.genymdhms
, …Le Java et la quasi-totalité des langages de programmation utilise l’anglais (dans les mot-clés et les librairies standards).
⇒ On doit programmer en anglais pour avoir la cohérence du code
Utiliser l’anglais permet aussi d’augmenter le nombre de personnes pouvant lire le code et d’avoir de nombreux exemples existants pour s’inspirer.
Méthodes modifiant l’état de l’objet
⇒ groupe verbal à l’infinitif.
boolean add(E element)
E set(int index, E element)
boolean removeAll(Collection<?> c)
Méthodes renvoyant une partie de l’état de l’objet ⇒ groupe nominal ou getter.
int size()
List<E> subList(int fromIndex, int toIndex)
int hashcode()
ListIterator<E> listIterator()
E get(int index)
Color getBackground()
float getOpacity()
Méthodes testant un prédicat sur l’objet ⇒ groupe verbal au présent.
boolean isEmpty()
boolean contains(Object o)
boolean equals(Object o)
Exemples :
String toString()
Object[] toArray()
Les règles ne sont pas absolues mais juste des conventions qui peuvent avoir des exceptions.
En général le plus simple est de s’inspirer de l’existant : par exemple la JDK et de bien réfléchir lorsqu’on souhaite déroger aux règles.
class User {
private boolean authenticated;
private String password;
public boolean checkPassword(String password) {
if (password.equals(this.password)) {
authenticated = true;
return true;
}
return false;
}
}
La méthode authentifie l’utilisateur alors qu’elle ne devrait que vérifier la validité du mot de passe d’après son nom.
Une fonction ne doit faire qu’une seule chose.
Pour cela, elle ne doit réaliser que des étapes de même niveau d’abstraction.
On décompose la fonction :
Pour faire la cuisine je dois (premier niveau d’abstraction) :
Pour choisir une recette, je dois (deuxième niveau d’abstraction):
void cook(){
// On choisir la recette
Food wantToEat = thinkAboutFood();
Recipe recipe = lookOnMarmiton(wantToEat);
// On réunit les ingrédients
openFridge();
(for Ingredient ingredient : recipe.getFreshIngredients()){
takeInFrige(ingredient);
}
closeFridge();
openCupboard();
...
// On suit la recette
...
}
Un programme est “bien conçu” s’il permet de :
Rechercher et caractériser les fonctions qu’un logiciel devrait avoir pour satisfaire les besoins de son utilisateur.
Hiérarchiser ces fonctions.
Utilisée pour créer mais aussi améliorer un logiciel (ou plus généralement un produit).
Fonction principale : la raison pour laquelle le logiciel est créé. Cette fonction peut être divisée en plusieurs fonctions simples.
Fonction contrainte : conditions que le produit doit vérifier mais qui ne sont pas sa raison d’exister (par exemple la sécurité).
Fonction complémentaire : ce qui facilite l’utilisation du logiciel, l’améliore ou le complète.
Un outil de l’analyse fonctionnelle : lister, décrire et hiérarchiser les fonctions.
Fonction principale :
Fonctions contraintes :
Fonctions complémentaires:
Livrable : produit destiné à la livraison : documentation, code, tests, etc…
Jalon : fin d’une étape ou évènement important.
Le début d’un projet et sa fin sont des jalons. On fixe des jalons intermédiaires pour mesurer l’avancée du projet.
Un jalon peut être un livrable lié à une date.
Développer un logiciel implique de :
Deux types de management pour y parvenir :
Méthode traditionnelle, inspirée par le BTP.
Passage d’une phase à l’autre uniquement quand la précédente est terminée et vérifiée.
Inconvénient : très peu réactif en cas d’erreur ou de modification nécessaire en cours de projet.
Un amélioration du modèle en cascade : limiter le retour aux étapes précédentes.
Standard depuis 1980.
Phase ascendante : renvoie de l’information sur la phase correspondante pour améliorer le logiciel.
Phase descendante : anticipation des attendus des étapes montantes.
Inconvénient : détache complètement la conception de la réalisation.
Objectifs :
Définition par le manifeste Agile (2001).
Exemples :
Théorisé par Kent Beck
Une classe ne doit avoir qu’une responsabilité = raison de changer
Programme ouvert pour l’extension, fermé à la modification
Vous devez pouvoir ajouter une nouvelle fonctionnalité :
interface Shape {
void draw();
}
public class Circle implements Shape {
Point center;
int radius;
public void draw(){ ... }
}
public class Rectangle implements Shape {
Point TopLeft, RightBottom;
public void draw(){ ... }
}
public class GraphicTools {
static void draw(Object[] shapes){
for(Shape s : shapes){
s.draw();
}
}
}
Les sous-types doivent être substituables par leurs types de base.
Si une classe A étend une classe B alors un programme P écrit pour manipuler des instances de type B doit avoir le même comportement s’il manipule des instances de la classe A.
Violation de LSP :
public void test(Rectangle r) {
r.setWidth (2);
}
r.setHeight(3);
if (r.getArea()!=3*2)
System.out.println(”bizarre !”);
Un carré est-il un rectangle ?
Pour les utilisateurs, votre carré a-t-il le même comportement que votre rectangle ?
La réponse : Dans ce cas, NON
## Dependency Inversion Principle (DIP)
### Principe :
Les modules d’un programme doivent être indépendants Les modules doivent dépendre d’abstractions Signification et objectifs :
Comment rendre le nommage des méthodes facile ?
En écrivant des méthodes courtes
De préférence une dizaine de ligne maximum.
Comment écrire des méthodes courtes
En extrayant le plus possible les partie du code d’une méthode à d’autres méthodes.
Conseils