CM2.md 12 KB


title: "Projets, CM2"

date: 2016-05-21

Conception d’un logiciel

Qu'est-ce-que la conception ?

  • « plan du code » (diagrammes de classes...)
  • au début du projet, permet de prévoir le code à écrire
  • pendant le projet, permet de suivre l’avancée du projet
  • à la fin du projet, permet de documenter le code (maintenance)

$\rightarrow$ doit correspondre aux fonctionnalités prévues et au code réel

En pratique

  • représentation graphique + explications
  • si possible, utiliser un formalisme classique (UML)
  • utiliser plusieurs niveaux d’abstraction (vue d’ensemble, vues détaillées)
architecture générale (MVC) architecture des vues

## Étape de conception

  • étape très importante, à faire avant le développement
  • évite ”d’avoir à tout casser” au cours du développement
  • permet de répartir le travail et de planifier plus finement

Quelques conseils

  • faire simple, logique, classique (MVC, design patterns...)
  • granularité : ne pas trop détailler sauf si important/incertain/complexe
  • vérifier a priori que la conception permet d’implémenter les fonctionnalités prévues dans le cahier des charges

Développement d’un logiciel

## Méthode pour écrire du code

  • découper en étapes et les ordonner
  • implémenter (coder, compiler, tester) étape par étape
  • comprendre le travail à faire (fonctionnalité/classe à implémenter)

    fonctionnalité : afficher le stock
    étapes : 
    1. méthode getLignes de Stock retournant un ensemble de string (tester avec un TU)
    2. affichage dans la VueConsole en utilisant getLignes (tester avec le main)
    3. connexion du signal d'affichage pour VueGraphique (tester avec le main)
    4. affichage dans la VueGraphique en utilisant getLignes (tester avec le main)
    

## Conseils sur le développement en équipe

  • faire le point régulièrement : travail fait, travail à faire
  • répartir le travail de façon à éviter les conflits (fichiers différents)
  • commits réguliers, branches si nécessaire
  • faire attention à respecter le cahier des charges et la conception

## Programmation en binômes

  • principe :
    • un secrétaire + un relecteur sur une même machine
    • les deux participent activement
    • changer les rôles fréquemment
  • intérêts :
    • moins d’erreurs
    • réflexions complémentaires
    • motivation, convivialité (ou pas, mais bon...)
  • à utiliser quand le travail n’est pas complètement trivial (donc tout le temps pour les projets L3)

Tests unitaires

  • souvent : test « avec un printf » $\rightarrow$ pas bien
  • principe des tests unitaires :
    • écrire des petites fonctions de test en même temps que le code
    • compiler toutes les fonctions de test dans un programme de test
    • exécuter le programme de test
    • vérification et non-régression automatiques
  • attention : détection d’erreurs $\neq$ preuve

$\rightarrow$ à utiliser pour les modules de base (traitement de données) voire plus

## Programmation par pseudo-code

  • principe :
    • commencer par écrire le pseudo-code de l’algo en commentaire
    • traduire chaque ligne de pseudo-code en code réel
    • laisser le pseudo-code en commentaire
void normaliserVector(std::vector<float> & v) {
    // calculer la somme des éléments
    float s = std::accumulate(v.begin(), v.end(), 0, std::plus<float>());
    // diviser chaque élément par la somme
    for (float & f : v) 
        f /= s;
}
  • intérêt :
    • code plus facile à écrire
    • code plus facile à relire

$\rightarrow$ très utile quand le code à écrire n’est pas trivial

## Gestion d’erreurs

  • problème difficile
  • se mettre d’accord sur la façon de faire au début du projet
  • outils possibles :
    • assertions
    • logs
    • codes de retour, variables d’état
    • exceptions

## Conventions de code

  • formatage du code, nommage des variables...
  • conventions à définir et à respecter au niveau du projet
  • permet d’avoir un code plus facile à lire
  • utiliser des conventions classiques ou les expliciter dans la documentation

## Exemple de conventions de code C++

  • notation dromadaire
  • un nom de classe commence par une majuscule :

    class Event ...
    
    • préfixe _ pour les attributs : cpp std::string _summary ;
  • préfixe ptr pour les pointeurs :

    icalcomponent * _ptrIcal ;
    
    • un nom de fonction commence par un verbe : cpp void updateDataFromIcal(); icalcomponent * getPtrIcal() const ;
  • maximum 80 caractères par ligne

  • ...

Quelques outils de développement à décider

  • langages, bibliothèques...
  • outils de compilation, test, déploiement
  • outils de gestion de code source (git, svn...)
  • outils de gestion de projets (github, redmine, trac, sourceforge...)

Gestion de projet avec github

Github

  • https://github.com
  • hébergement de dépôts git
  • gestion des collaborateurs + droits d'accès
  • gestion de projet basique (tickets, jalons, pulls request, wiki, stats...)

Créer un projet

Gestion des collaborateurs

Ajouter un jalon

Voir les jalons

Ajouter un ticket

Voir les tickets

Fermer un ticket

  • via l'interface web
  • via les messages de commit : mise en place du code, close #1

Gestion de code source avec git

Git

  • système de gestion de code source
  • fonctionnalités : journalisation, synchronisation...
  • implémentations : client console, gui
  • notions principales :
    • commit
    • dépôt

Notion de commit

  • état des fichiers versionnés
  • seules les modifications par rapport au commit précédent sont stockées
  • branches
  • historique des commits

            H -- I
           /
    A -- B -- C -- F -- G
      \      /
       D -- E
    

Notion de dépôt (repository)

  • ensemble des commits du projet
  • système décentralisé :
    • chaque collaborateur a un dépôt complet et équivalent
    • les dépôts peuvent se synchroniser
    • souvent, on synchronise via un dépôt sur un serveur (github)

Workflow git

  • initialisations :
    • configurer le client git
    • créer un dépôt git
  • déroulement du projet :
    • ajouter, modifier, supprimer des fichiers
    • valider les modifications (commit)
    • récupérer les modifications du serveur (pull)
    • corriger les conflits éventuels
    • envoyer les modifications sur le serveur (push)

Configurer le client git

  • installer git :

    sudo apt-get install git
    
  • configurer l'utilisateur :

    git config --global user.name "Julien Dehos"
    git config --global user.email dehos@nimpe.org
    
  • paramétrer le client :

    git config --global core.editor emacs
    git config --global http.proxy http://user:pass@proxyhost:proxyport
    

Quelques commandes git (1)

| | ---|---| git clone | récupère un dépôt | git status | affiche l'état courant des fichiers | git add <fichiers> | demande à Git de versionner des fichiers | git mv <nom1> <nom2> | renomme des fichiers versionnés | git rm <fichiers> | supprime des fichiers versionnés | git commit <fichiers> | valide les modifications des fichiers spécifiés | git commit -a | valide les modifications de tous les fichiers versionnés | git commit -am "message" | valide les modifications avec le message donné | git log | affiche la liste des commits | git diff | affiche les modifications par rapport au dernier commit| git checkout -- . | supprime les modifications (revient au commit) |

Quelques commandes git (2)

| | ---|---| git pull | récupère les commits distants et les intègre dans le dépôt local | git push | envoie les commits du dépôt local sur le dépôt distant | git branch | affiche les branches locales | git ls-remote | affiche les branches distantes | git branch <branche> | crée une nouvelle branche | git checkout <branche> | change de branche | git push -u origin <branche> | envoie une nouvelle branche distante | git merge <branche> | fusionne une branche dans la branche courante |

Quelques conseils

  • faire des commits réguliers et correspondant à des petites tâches successives (ou à des tickets)
  • ne pas commiter un projet cassé (par exemple, du code qui ne compile pas)
  • ne pas versionner les fichiers auto-générés
  • utiliser git mv et git rm pour déplacer et supprimer des fichiers commités
  • éviter les conflits potentiels en organisant le travail de telle sorte que les intervenants aient à travailler sur des fichiers différents

Récupérer un dépôt github

$ git clone https://juliendehos@github.com/juliendehos/projet_l3

Clonage dans 'projet_l3'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Dépaquetage des objets: 100% (3/3), fait.
Vérification de la connectivité... fait.

Ajouter des fichiers

$ git add proto.cpp Makefile 

$ git status

Sur la branche master
Votre branche est à jour avec 'origin/master'.
Modifications qui seront validées :
  (utilisez "git reset HEAD <fichier>..." pour désindexer)

	nouveau fichier : Makefile
	nouveau fichier : proto.cpp

Valider un commit

$ git commit -am "mise en place du code, close #1"

[master eab4260] mise en place du code, close #1
 2 files changed, 9 insertions(+)
 create mode 100644 Makefile
 create mode 100644 proto.cpp

Envoyer des commits sur un serveur

$ git push

Password for 'https://juliendehos@github.com': 
Décompte des objets: 4, fait.
Delta compression using up to 4 threads.
Compression des objets: 100% (3/3), fait.
Écriture des objets: 100% (4/4), 447 bytes | 0 bytes/s, fait.
Total 4 (delta 0), reused 0 (delta 0)
To https://juliendehos@github.com/juliendehos/projet_l3
   bd1f597..eab4260  master -> master

Branches locales

  • créer une branche locale :

    $ git branch proto2
    
  • voir les branches locales :

    $ git branch
    * master
    proto2
    
  • changer de branche :

    $ git checkout proto2
    Basculement sur la branche 'proto2'
    

Branches distantes

  • voir les branches distantes :

    $ git ls-remote
    From https://juliendehos@github.com/juliendehos/projet_l3
    4fca7ad38b299acdb7453547d5c9fc1d2494e4cc	HEAD
    4fca7ad38b299acdb7453547d5c9fc1d2494e4cc	refs/heads/master
    
  • envoyer une nouvelle branche sur le serveur origin :

    $ git push -u origin proto2
    Password for 'https://juliendehos@github.com': 
    Décompte des objets: 2, fait.
    Delta compression using up to 4 threads.
    Compression des objets: 100% (2/2), fait.
    Écriture des objets: 100% (2/2), 266 bytes | 0 bytes/s, fait.
    Total 2 (delta 0), reused 0 (delta 0)
    To https://github.com/juliendehos/projet_l3
    * [new branch]      proto2 -> proto2
    La branche proto2 est paramétrée pour suivre la branche distante proto2 depuis origin.
    

Fusion de branches

  • exemple :

    -- B (proto2)               -- B -- (proto2)
    /                  ->       /       \
    A -- C (master)             A -- C -- D (master)
    
  • passer sur la branche qui doit recevoir la fusion :

    $ git checkout master
    Basculement sur la branche 'master'
    
  • fusionner :

    $ git merge proto2 
    Merge made by the 'recursive' strategy.
    proto2.cpp | 0
    1 file changed, 0 insertions(+), 0 deletions(-)
    create mode 100644 proto2.cpp
    
  • éventuellement, vérifier le log :

    $ git log --oneline --decorate --graph
    *   82eb957 (HEAD, master) Merge branch 'proto2'
    |\  
    | * e29caa2 (origin/proto2, proto2) début proto2
    * | 7c13fc0 modif proto1
    |/  
    * 4fca7ad (origin/master) mise en place du code, close #1
    
  • ne pas oublier de pusher

Travail à réaliser

## Au début du projet

  • sur github :
    • créer un compte pour chaque étudiant (ou binôme) du groupe
    • créer un dépôt pour le projet du groupe (et ajouter les collaborateurs)
  • faire une conception prévisionnelle du logiciel
  • faire un planning prévisionnel (et les tickets/jalons correspondants sur github)

## Tout au long du projet

  • utiliser git pour réaliser le projet (code, documentations, cahier des charges, rapport...)
  • utiliser github pour suivre le déroulement du projet
  • faire le point régulièrement pour mettre à jour la conception du logiciel et la répartition du travail