Aller au contenu principal

Concepts de base

Un objet possède 3 caractéristiques fondamentales :

  • une identité,
  • un type,
  • une valeur

Encapsulation

Encapsulation

L'encapsulation est un mécanisme consistant à rassembler les données et les méthodes au sein d'une structure en cachant l'implémentation de l'objet.

Refactorisation

Refactorisation

La refactorisation est le processus de modification du code source d'un programme pour en améliorer la structure interne, sans en changer le comportement externe.

Le processus de modification d'un logiciel est de telle sorte que :

  • le comportement externe ne soit pas modifié
  • la structure interne soit améliorée.

La refactorisation dans le développement se fait petit à petit pour obtenir du code sain, au fur et à mesure du développement. C'est en construisant le système que l'on découvre comment l'améliorer.

Risques

La refactorisation introduit des risques comme l'introduction de bugs subtils. Si cette dernière est mal faite, elle peut rammener le développement plusieurs jours en arrière.

Principes SOLID

Les 5 Principes
  1. Single Responsability Principle (SRP) : Une classe ne doit avoir qu'une seule responsabilité
  2. Open/Closed Principle (OCP): Le programme est ouvert pour l'extension mais fermé à la modification
  3. Liskov Substitution Principle (LSP) : Les sous-types doivent être substituables par leurs types de base
  4. Interface Segregation Principle (ISP) : Éviter les interfaces qui contiennent beaucoup de méthodes
  5. Dependency Inversion Principle (DIP) : Les modules d'un programme doivent être indépendants et kes modules doivent dépendre d'abstraction

Le but des principes solides est de garantir la maintenabilité d'un programme, c'est-à-dire sa capacité à :

  • Absorber les changemeents avec un minimum d'effort ;
  • Implémenter les nouvelles fonctionnalités sans toucher aux anciennes ;
  • Modifier les fonctionnalités existantes en modifiant localement le code.

Exemple : Violation de LSP

Violation de LSP
class Bird:
def fly(self) -> str:
return "Je vole!"

class Penguin(Bird):
def fly(self) -> str:
raise Exception("Je ne peux pas voler!")

Dans cette exemple, la classe Penguin ne respecte pas le principe de substitution de Liskov car elle ne peut pas être substituée à la classe Bird sans causer d'erreur.

Une meilleure hiérarchie des classes permet de résoudre ce problème :

Meilleure hiérarchie pour respecter LSP
from abc import ABC, abstractmethod

class Bird(ABC):
@abstractmethod
def move(self) -> str:
pass

class FlyingBird(Bird):
def move(self) -> str:
return "Je vole!"

class WalkingBird(Bird):
def move(self) -> str:
return "Je marche!"

class Penguin(WalkingBird):
pass

class Sparrow(FlyingBird):
pass