Aller au contenu

Introduction

Dans cette unité, nous allons récapituler l'approche historique du développement logiciel, fournir une définition formelle du développement logiciel, retracer les problèmes courants et présenter les éléments liés au développement logiciel agile le plus répandu aujourd'hui.

Résumé de la lecture

Le développement logiciel est complexe, car les exigences sont souvent inconnues ou tendent à évoluer. Une approche de développement qui tente de planifier toutes les éventualités ne favorise pas le succès. De nos jours, nous nous concentrons plutôt sur des facteurs qui favorisent une adoption rapide et une flexibilité.

Processus et modèles de développement logiciel

Deux définitions :

  • Processus de développement logiciel : Un ensemble d'activités liées qui mènent à un produit logiciel.
  • Modèle de processus de développement logiciel : Représentation simplifiée d'un processus logiciel.

Éléments clés, faisant partie de tout processus logiciel :

  1. Spécification : Définir les attentes et les limitations du résultat idéal.
  2. Conception et mise en œuvre : Produire le logiciel.
  3. Validation : S'assurer que le logiciel fait effectivement ce que le client souhaite.
  4. Évolution : Adapter le logiciel aux exigences modifiées.

De nombreux modèles ont été proposés et suivis en pratique. Nous examinerons de plus près trois exemples représentatifs.

Cascade

  • Le premier modèle de processus de développement logiciel.
    • Dérivé des modèles d'ingénierie des systèmes généraux existants, 1970.
  • Orienté documents et dirigé par la planification. Idéalement :
    • Chaque activité se termine par un document. Doit être "approuvé", avant de passer à l'activité suivante.
    • Toutes les activités du processus doivent être planifiées avant la réalisation.
  • Philosophie : Si chaque phase a été parfaitement réalisée, le résultat est un logiciel parfait.
    • Un seul passage linéaire pourrait suffire.

Activités

Remarque : Le modèle en cascade semble strictement linéaire, mais des révisions occasionnelles des activités précédentes sont considérées.

Activités en cascade, selon Ian Sommerville :

  1. Analyse et définition des exigences : "Les services, contraintes et objectifs du système sont établis par consultation avec les utilisateurs du système. Ils sont ensuite définis en détail et servent de spécification du système."
  2. Conception du système et du logiciel : "Le processus de conception des systèmes alloue les exigences soit aux systèmes matériels soit aux systèmes logiciels en établissant une architecture générale du système. La conception du logiciel implique l'identification et la description des abstractions fondamentales du système logiciel et de leurs relations."
  3. Mise en œuvre et tests unitaires : "Au cours de cette étape, la conception du logiciel est réalisée sous forme de programmes ou d'unités de programme. Les tests unitaires impliquent de vérifier que chaque unité respecte sa spécification."
  4. Intégration et tests du système : "Les unités de programme individuelles ou les programmes sont intégrés et testés en tant que système complet pour s'assurer que les exigences logicielles ont été satisfaites. Après les tests, le système logiciel est livré au client."
  5. Exploitation et maintenance : "Normalement (bien que ce ne soit pas nécessairement le cas), c'est la phase du cycle de vie la plus longue. Le système est installé et mis en usage pratique. La maintenance implique de corriger les erreurs qui n'ont pas été découvertes lors des étapes antérieures du cycle de vie, d'améliorer la mise en œuvre des unités du système et d'améliorer les services du système à mesure que de nouvelles exigences sont découvertes."

Réalité

  • Il est impossible d'anticiper toutes les exigences à un moment donné, la communication via les documents peut déformer les besoins du client.
    • Les activités et leurs documents seront approuvés, bien qu'ils soient incomplets.
    • Un seul passage n'est jamais suffisant.
    • Les révisions seront la norme, et non l'exception.
  • Le modèle en cascade n'est pas la façon dont les humains résolvent les problèmes :
    • Nous ne restons pas bloqués sur un problème jusqu'à ce qu'il soit résolu parfaitement, et nous ne passons à l'étape suivante que lorsque tout est résolu.
    • Nous ne connaissons souvent pas toutes les exigences à l'avance, nous changeons souvent d'avis.

Avertissement

Le modèle en cascade est toujours populaire parmi les gestionnaires, car il donne une illusion de planification.

Quand utiliser

Le modèle en cascade ne doit être utilisé que lorsque...

  • Peu ou pas d'évolution des exigences est à prévoir.
  • Le contexte peut être bien formalisé, par exemple un contexte très orienté vers les mathématiques.

Info

La forme la plus extrême du modèle en cascade est une approche générative et formelle : Les documents et le code ne sont pas écrits à la main, mais générés ou déduits des étapes précédentes. Idéalement, lorsque les transitions formelles sont démontrablement correctes, tout ce qui est généré doit également être correct.

Développement incrémental

  • Le modèle de développement logiciel le plus courant
  • Philosophie :
    • Alterner spécification et développement
    • Exposer le produit au client dès que possible
    • Évoluer à chaque itération

Activités

  • Début : Commencer par une description approximative de la fonctionnalité requise. Se concentrer sur les scénarios clés.
  • Itérations :
    • Spécification : Réviser la spécification du logiciel
    • Développement : Réviser la mise en œuvre du logiciel
    • Validation : Réviser la validation du logiciel
  • Fin : Le client accepte la version finale

Avantages et inconvénients

Avantages par rapport au modèle en cascade :

  • Le coût des changements est réduit, moins de documents nécessitent une révision en cas de changement
  • Les retours du client sont déjà pris en compte tout au long du développement, ce qui réduit le risque de manquer des exigences
  • Grâce aux démonstrations, les progrès sont plus visibles pour le client
  • Une livraison et un déploiement rapides permettent de bénéficier plus tôt de la fonctionnalité de base

Inconvénients :

  • Les progrès sont moins visibles pour la direction
    • La création fréquente de documents pour suivre les progrès peut même constituer une surcharge et ralentir les choses
  • Les changements tendent à corrompre le système à mesure qu'il se développe
    • Temps supplémentaire nécessaire pour refactorer / réorganiser (nettoyer) le système
  • L'évolution des structures centrales peut être problématique pour les projets à grande échelle avec de nombreuses équipes
    • Les équipes ont besoin de structures et de responsabilités claires pour collaborer

Quand utiliser

Le modèle incrémental (agile) doit être utilisé lorsque...

  • Les exigences des utilisateurs changent (entreprises, commerce électronique, applications personnelles)
  • Les exigences du client ou les souhaits du client ne sont pas clairs
  • Le client a besoin d'un accès rapide à la fonctionnalité de base opérationnelle

Avertissement

Agile ne doit pas être considéré comme une excuse pour abaisser les normes d'ingénierie, en particulier en ce qui concerne la qualité du code et les tests. Agile concerne les itérations fréquentes pour obtenir des retours rapides des clients. Il ne s'agit pas de compromettre le projet pour des accélérations temporaires.

Orienté Réutilisation

  • Un modèle de développement logiciel populaire
  • Philosophie :
    • Ne réinventez pas la roue. Utilisez des composants logiciels existants pour accélérer le développement.
    • Les composants existants peuvent être :
      • Systèmes similaires, pour trouver de l'inspiration
      • Code existant de systèmes hérités ou connexes
      • Cadres et bibliothèques dédiés

Activités

  1. Spécification des exigences : (Même que pour les autres processus logiciels)
  2. Analyse des composants : Recherchez des composants existants pour mettre en œuvre cette spécification. En général, il n'y a pas de correspondance exacte. Les composants peuvent seulement fournir une couverture fonctionnelle partielle.
  3. Modification des exigences : Analysez les exigences par rapport aux composants découverts. Adaptez les exigences aux composants, lorsque cela est possible. Si nécessaire, étendez la recherche de composants.
  4. Conception du système avec réutilisation : Concevez un cadre pour le système, ou réutilisez un cadre existant, basé sur les composants sélectionnés. Concevez des solutions sur mesure lorsque aucun composant prêt à l'emploi n'est disponible.
  5. Développement et intégration : Comblez les lacunes, c'est-à-dire développez les composants manquants et intégrez-les dans un système.
  6. Validation du système : (Même que pour les autres processus logiciels)

Avantages et inconvénients

Avantages par rapport au modèle en cascade et au modèle incrémental :

  • Accélération du développement pour les composants standard
  • Gains de sécurité pour les composants standard

Inconvénients :

  • Invitation à l'enfer des dépendances
  • Résultat imprévisible lorsque les composants sont utilisés dans un contexte étranger

Recommandation

Soyez sélectif avec les dépendances du projet. Chaque composant est aussi une dépendance et un risque potentiel. Faites une évaluation claire des gains par rapport aux coûts avant d'intégrer toute technologie ou composant.

Une catastrophe de réutilisation notable

Explication simplifiée de la catastrophe de l'Ariane V88 :

  1. Les ingénieurs réutilisent le logiciel de la fusée Ariane 4 pour créer l'Ariane 5
    • L'Ariane 5 est conçue pour transporter plus de satellites par lancement, afin de rendre les lancements moins coûteux
  2. L'Ariane 5 est conçue plus grande, et avec un moteur plus puissant
    • Poussée Ariane 4 + propulseurs : ~ 3780 kN
    • Poussée Ariane 5 + propulseurs : ~ 8090 kN
  3. L'Ariane 5 décolle le 4 juin 1996
    • Les moteurs fonctionnent comme prévu, la poussée est significativement plus élevée que pour l'Ariane 4
    • L'Ariane 5 monte "plus vite" que l'Ariane 4
    • Les valeurs numériques du chemin de vol résultant sont dans des plages plus élevées
  4. L'ordinateur de la fusée suit le chemin de vol avec le logiciel réutilisé de l'Ariane 4
    • L'ordinateur de l'Ariane 5 a un processeur 64 bits, utilise des flottants non signés
    • Le logiciel de l'Ariane 4 est écrit pour des processeurs 16 bits
      • L'Ariane 5 convertit les valeurs en int non signé 16 bits
      • La valeur maximale est un entier non signé 16 bits : 65535
      • La conversion de valeurs au-dessus de 65535 entraîne un dépassement
    • 40 secondes après le décollage, une valeur numérique du chemin de vol dépasse 65535
      • L'Ariane 5 convertit la valeur sans vérification de dépassement
      • L'Ariane 5 fournit des données incorrectes au logiciel réutilisé de l'Ariane 4
  5. Le module logiciel réutilisé pour le calcul du chemin de vol plante
    • Le logiciel de suivi du chemin de vol ne peut pas gérer le dépassement de valeur
    • Le module plante, renvoie maintenant des rapports de plantage au lieu de résultats numériques au calculateur principal
    • Le calculateur principal interprète mal le rapport de plantage comme des données de vol
      • Cette interprétation erronée suggère que la fusée est hors de course
      • Une fusée hors de course est potentiellement dangereuse
    • Le calculateur principal déclenche la destruction automatique
  6. La fusée et tous les satellites à bord sont détruits
Qui est à blâmer ?

Trois défauts d'ingénierie : Réutilisation de logiciel dans un contexte étranger, conversion de type sans vérification de dépassement, manque de sécurité de type pour l'interprétation des résultats.

Développement logiciel Agile

  • Agile est une approche basée sur quatre piliers du manifeste :
    1. Les individus et les interactions plutôt que les processus et les outils
    2. Le logiciel fonctionnel plutôt que la documentation exhaustive
    3. La collaboration avec le client plutôt que la négociation de contrat
    4. Réagir au changement plutôt que suivre un plan
  • Le développement Agile maximise le modèle itératif
    • S'adapter aux exigences incertaines ou changeantes est considéré comme plus important que la planification minutieuse
    • Le fait que l'utilisateur ne sache pas ce qu'il veut avant de voir une démo est considéré comme la règle, et non l'exception

Remarque : L'agilité n'est pas un critère lorsqu'il s'agit de systèmes critiques pour la sécurité (aviation, équipement médical, réacteur nucléaire...)

L'Agile n'est pas nécessairement bon

Récemment, l'approche Agile (en particulier les cadres orientés gestion) est devenue de moins en moins populaire, associant le style de travail à une augmentation des taux d'échec des projets. Cependant, la critique vise principalement les méthodes de gestion Agile, plutôt que l'ouverture au développement itératif en soi.

Scrum

Scrum est une façon de matérialiser l'approche Agile en tant que philosophie de gestion de projet.

Facteurs clés :

  • Organiser les progrès en Sprints de durée gérable, typiquement de 2 à 4 semaines.
    • Chaque sprint définit un objectif / état cible de fonctionnalité souhaitée.
  • Délégation de la responsabilité du sprint à un maître de Scrum.
    • Le rôle de maître de Scrum peut être tourné parmi les développeurs.
    • Le maître de Scrum est plus proche des développeurs qu'un "Product owner".

Sprints

L'élément central des sprints est le suivi précis des fonctionnalités réalisées et manquées.

  • "Planification du sprint" : Le maître de Scrum et le product owner déterminent une durée et un objectif de sprint raisonnables.
  • "Réunion quotidienne" : Le maître de Scrum commence chaque jour par une réunion de 15-20 minutes.
    • Pour chaque participant, répondre à :
      1. Qu'ai-je complété hier ?
      2. Sur quoi vais-je travailler aujourd'hui ?
      3. Suis-je bloqué par quelque chose ?
  • "Revue du sprint" : L'équipe se réunit pour évaluer quels objectifs de sprint ont été atteints. Peut se faire lors de moments intermédiaires du sprint.
  • "Recettes du sprint" : L'équipe se réunit pour discuter des dynamiques de groupe / outils. Peut se faire lors de moments intermédiaires du sprint.

Crédits de l'image : Atlassian

Kanban

Kanban est une méthodologie alternative de gestion Agile.

  • Kanban repose sur une forte visualisation des tâches en cours
  • Kanban : japonais pour "Carton"
  • Les tâches sont représentées par des cartes
  • Chaque développeur a une colonne dans une grille (tableau)
  • Chaque tâche passe par des étapes :
    1. À faire
    2. En cours
    3. Revue de code
    4. Terminé

Crédits de l'image : Atlassian

La plupart des solutions de codage collaboratif (GitLab, GitHub) supportent nativement le Kanban, pour coordonner les tâches :

Source : Documentation GitLab

Philosophie Kanban

  • Flux continu d'attribution des tâches (en contraste avec les sprints Scrum)
  • Un gestionnaire peut facilement redistribuer ou prioriser les tâches, car il "voit" qui est disponible ou en train de travailler sur quelque chose.
  • Limiter le "Travail en cours" est une activité visuelle, les développeurs ne souffrent pas du changement constant de contexte.

Pratiques d'ingénierie

  • Agile est une philosophie autour de l'adaptation dynamique aux exigences modifiées.
  • La capacité à s'adapter rapidement aux exigences modifiées dépend de la capacité à faire des itérations rapides.
    • Des itérations plus rapides ne peuvent pas être imposées, mais sont le produit de bonnes habitudes d'ingénierie
    • Les prérequis d'Agile sont presque exclusivement liés aux habitudes des développeurs et à la qualité du code.

Qualité du code

  • En fin de compte, tout se résume à des pratiques d'ingénierie, notamment la qualité du code
  • Considérez l'exemple de code suivant :
/**
 * Vaj ghob Hutlhbogh vay''e'
 */
public static boolean test(int input) {
  int x = -1;
  boolean[] yyy = new boolean[input];
  while (!(x > input-2)) {
    if (input % (x + 2) == 0) {
      yyy[x + 1] = true;
    } else {
      yyy[x + 1] = !true;
    }
    x++;
  }
  for (int k = input - 2; k >= 1; k--) {
    if (yyy[k] == true) {
      return false;
    }
  }
  return true;
}
  • Trois questions :
    1. Que fait ce code ?
    2. L'implémentation est-elle correcte ?
    3. Quelle est la facilité d'adaptation de ce code à une exigence modifiée ?

Directives pour un bon code :

  • Le code devrait être doit être aussi facile à lire que possible (style)
    • Commentez votre code
    • Utilisez des noms de variables et de fonctions clairs
    • Utilisez une indentation cohérente
    • Favorisez la clarté plutôt que la brièveté
    • Évitez les optimisations de performance, sauf si nécessaire
    • Utilisez le polymorphisme au lieu des vérifications de type
  • Le code devrait être doit être correct et sécurisé (sémantique)
    • Testez tout votre code
    • Testez toutes les conditions
    • Testez aussi souvent que possible
    • Limitez l'accès aux variables
    • Codez contre des interfaces
    • Codez de manière défensive
  • Le code devrait être doit être facile à changer
    • Éliminez les duplications de code
    • Respectez l'encapsulation
    • Respectez le principe de Liskov

Les problèmes les plus difficiles

Il n'y a que deux choses difficiles en informatique : l'invalidation du cache et la nomination des choses.
--Phil Karlton

CI/CD

Même le meilleur codeur fait des erreurs ou passe une mauvaise journée. Que peut-on faire pour garantir la qualité du code ?

Utilisez des contrôles de qualité automatisés. Rejetez rigoureusement le mauvais code.

  • Les pipelines de "Continous integration / Continuous delivery" garantissent que :
    • Chaque changement logiciel respecte la qualité du code
      • Le code se compile
      • Tous les tests passent
      • Le code est entièrement documenté
      • Le code respecte les règles de formatage
      • ... et bien plus encore
    • Chaque changement accepté déclenche automatiquement une construction
      • Les exécutables sont continuellement générés et livrés au client
  • Intérêt principal : Peu importe ce qui se passe, le code ne peut que s'améliorer, pas se détériorer
    • Il y a toujours une version stable du logiciel
    • Tout ce qui fonctionnait déjà fonctionnera également à l'avenir

Devoir

Pour la semaine prochaine, veuillez contribuer au deux devoir suivant :

Pires pratiques

Écrivez la version la plus compliquée et difficile à maintenir de la fonction ci-dessous tout en restant fonctionnelle. Créez votre liste de caractéristiques de mauvais code.

import java.util.LinkedList;

/**
 * Supprime tous les éléments d'une liste de chaînes fournie contenant un "M".
 */
public List<String> removeAllElementsWithM(List<String> unfilteredList) {
  List<String> filteredList = new LinkedList<>();
  for (String element : unfilteredList) {
    if (!element.contains("M")) {
      filteredList.add(element);
    }
  }
  return filteredList;
}

Partagez la pire version qui fonctionne sur mattermost.

Littérature

Inspiration et lectures supplémentaires pour les esprits curieux :