IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Affichage des résultats du sondage: Quels sont, selon vous, les points clés pour une programmation défensive ?

Votants
40. Vous ne pouvez pas participer à ce sondage.
  • Ne pas faire confiance aux données entrées par les utilisateurs

    34 85,00%
  • Utiliser une abstraction de base de données

    9 22,50%
  • Ne pas réinventer pas la roue :

    10 25,00%
  • Ne pas faire confiance aux développeurs

    10 25,00%
  • Écrire un code SOLID

    12 30,00%
  • Écrire des tests

    21 52,50%
  • Autres (à préciser en commentaire)

    5 12,50%
Sondage à choix multiple
Débats sur le développement - Le Best Of Discussion :

Un développeur propose quelques points clés pour la programmation défensive


Sujet :

Débats sur le développement - Le Best Of

  1. #61
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    605
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 605
    Points : 670
    Points
    670
    Par défaut
    À mes yeux, la programmation défensive se fonde sur la méfiance quant à l'environnement sur lequel on s'exécute (les données lues sont-elles valides, le service distant que nous appelons est-il fiable, etc.) et repose surtout sur :

    - Des objets métiers contenant en leur sein des contrôles "d'invariants" : à n'importe quel moment, un objet métier que j'ai doit se considérer valide du point de vue du contenu de ses variables membres.

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    /**
     * Un code de commune.
     */
    public class CodeCommune extends Id
    {
       /** Ensemble des codes communes valides connus. Il a été préalablement alimenté en cache statique. */
       private static Set<CodeCommune> COMMUNES = new HashSet<>(); 
     
       /**
        * Vérification de la validité de l'objet métier.
        */
       public void anomalies(Anomalies anomalies)
       {
          // Le code de la commune doit être alimenté.
          if (isBlank(getId()))
             anomalies.declare(ERREUR, "anomalie.code_commune_vide");
          else
          {
             // Le code de la commune doit être associé à un code département.
             if (getCodeDepartement() == null || isBlank(getCodeDepartement().getId()))
                anomalies.declare(ERREUR, "anomalie.code_commune_sans_departement", this);
             else
             {
                // Le département doit être valide.
                anomalies.examine(getCodeDepartement());
     
                // Vérifier que la commune est valide.
                if (COMMUNES.contains(this) == false)
                   anomalies.declare(ERREUR, "anomalie.code_commune_non_francais", this);
             }
          }
       }
     
       // ...Autres méthodes de l'objet non présentées ici...
    }

    L'idée étant d'arriver à une situation où "L'on peut transporter dans son programme un objet aussi faux que l'on veut, mais l'on ne peut pas l'utiliser." :
    Je viens de lire un objet de la base, ce n'est pas moi qui l'ai écrit, et il est complètement baroque. Je peux faire autant d'appels de setters que je veux pour le corriger.

    Mais (selon la rigueur que l'on s'impose) :
    Moyenne : aucun service ou DAO ne peut utiliser l'objet tant qu'il n'aura pas une liste d'anomalies d'auto-contrôle vide,
    Forte : aucun de ses getters ne renverra de valeur tant qu'il ne sera pas valide, et ces méthodes lèveront une exception à la place.

    - Emploi d'assertions : pré-conditions, post-conditions.
    - Emploi d'un jeu d'exceptions élaborées pour décrire tous les problèmes rencontrés avec gestion de leur propagation, enrichissement et rethrow, catch aux endroits appropriés si légitimité à le faire.

    - Typage fort. Aucun String, int, double, ne se balade tout nu dans des paramètres de fonctions, si possible, quand il serait possible d'utiliser un objet métier à la place.
    par exemple, la fonction présentée est bonne : payTo(Account $to, $amount)
    alors que celle-ci payTo($banque, $agence, $guichet, $numeroCompte, $amount) serait plus risquée : banque + agence + guichet + numéro de compte = Account, certes, mais il n'y a plus de vérification aisée que ces quatre premiers paramètres sont bien cohérents entre-eux.

    + d'autres pratiques, nombreuses, comme : des DAO vérifiant avant écriture / update que les objets qu'ils vont persister sont valides avant de le faire.

  2. #62
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Points : 2 918
    Points
    2 918
    Par défaut
    J'ai l'impression qu'on confond allègrement programmation défensive et qualité dans ce billet de blog (et aussi dans la définition Wikipédia qui mélange tout et n'importe quoi). La qualité peut être un but mais la programmation défensive n'en est pas un. C'est juste une technique qui est hyper mal définie ici.

    • OK pour la programmation par contrat (pré et post conditions)
    • OK pour ne pas faire confiance aux entrées utilisateur


    Mais en quoi faire du SOLID, des code review, des tests ou simplement "réduire le nombre de bugs" c'est de la programmation défensive ?

    Si l'on pose la question différemment : qu'est-ce qui dans le fait de coder n'est pas de la programmation défensive, du coup ?

    Coup de chapeau aussi à la généralisation la plus stupide de tous les temps :

    developers shouldn’t trust others developers’ code
    Qui vient en contradiction totale avec "don't reinvent the wheel", puisque si on ne fait pas confiance au code de ses propres collègues, on va encore moins réutiliser des librairies tierces, hein...

  3. #63
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 192
    Points : 28 073
    Points
    28 073
    Par défaut
    Citation Envoyé par Luckyluke34 Voir le message
    J'ai l'impression qu'on confond allègrement programmation défensive et qualité dans ce billet de blog (et aussi dans la définition Wikipédia qui mélange tout et n'importe quoi). La qualité peut être un but mais la programmation défensive n'en est pas un. C'est juste une technique qui est hyper mal définie ici.
    [...]
    Mais en quoi faire du SOLID, des code review, des tests ou simplement "réduire le nombre de bugs" c'est de la programmation défensive ?
    Oui et non. Si qualité et programmation défensive sont 2 notions différentes et apparemment sans lien, toutes les notions de qualité citées contribuent à avoir un code de meilleures qualité, un code bien maitrisé et compris par les développeurs, bien plus aisément maintenable,etc ... Cela suppose aussi que les choses ont été faites correctement en amont du code, que donc le besoin a été compris, que le périmètre d'action du code a bien été compris et cerné, etc...
    Tout ça n'est pas, en soi, de la programmation défensive à proprement parlé, mais cela contribue à rendre, en soi, le code plus robuste, à réduire les potentielles surfaces d'attaques, un code beaucoup mieux maitrisé par l'équipe de développement, dans ses qualités, dans ses défauts, dans ses limites.
    Ça constitue donc quand même le premier échelon de la programmation défensive.

    Citation Envoyé par Luckyluke34 Voir le message
    Coup de chapeau aussi à la généralisation la plus stupide de tous les temps :
    Cette généralisation là n'est pas stupide, bien au contraire. Non, il ne faut pas confiance aux codes des collègues.
    Mais pas dans le sens ou les collègues font que de la me***, mais plutôt dans le sens que ce n'est pas parce que c'est le collègue qui a écrit ce code, que ce code est exempt de bugs, de possible mauvaise compréhension du besoin, de mauvaise implémentation, etc ...
    Et le prolongement est évidemment qu'il ne faut surtout pas non plus faire confiance à son propre code personnel, encore moins je dirais même. On est les plus mal placés pour juger et analyser le code qu'on écrit soi-même. Il ne faut pas hésiter à se remettre en question, il ne faut pas hésiter à penser que ce que l'on a écrit est probablement loin d'être la meilleur qualité qui aurait pu être produite.
    C'est dans ce même état d'esprit que, pour une meilleure pertinence, les équipes qui font les tests (ou codent les tests automatiques suivant les organisations), ne doivent absolument pas être composées de membre participant à l'écriture du code. Les équipes qui testent ne doivent pas être celles qui réfléchissent à la résolution des problèmes.

    Citation Envoyé par Luckyluke34 Voir le message
    Qui vient en contradiction totale avec "don't reinvent the wheel", puisque si on ne fait pas confiance au code de ses propres collègues, on va encore moins réutiliser des librairies tierces, hein...
    En contradiction totale, oui. Et de l'avis assez majoritaire dans les réactions de ce sujets que cet argument là est, lui par contre, bien stupide, surtout dans un contexte de mise en avant de la programmation défensive.

    Comme j'ai pu le dire auparavant, faire confiance à un framework dont on ne connait rien (quel qu’en soit la raison, souvent parce que l'on ne prend même pas le temps de savoir ce qu'est ce framework à la mode), c'est un peu programmer volontairement de potentielles failles dans la carapace que l'on veut justement renforcer.
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  4. #64
    Membre émérite
    Inscrit en
    Janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Janvier 2011
    Messages : 805
    Points : 2 918
    Points
    2 918
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Tout ça n'est pas, en soi, de la programmation défensive à proprement parlé, mais cela contribue à rendre, en soi, le code plus robuste, à réduire les potentielles surfaces d'attaques, un code beaucoup mieux maitrisé par l'équipe de développement, dans ses qualités, dans ses défauts, dans ses limites.
    Ça constitue donc quand même le premier échelon de la programmation défensive.
    Donc ce n'est pas de la programmation défensive à proprement parler... mais c'est le premier échelon de la programmation défensive ? J'avoue que j'ai du mal à comprendre là. En tout cas, ça n'aide pas à donner une définition plus claire.

    Citation Envoyé par sevyc64 Voir le message
    Comme j'ai pu le dire auparavant, faire confiance à un framework dont on ne connait rien (quel qu’en soit la raison, souvent parce que l'on ne prend même pas le temps de savoir ce qu'est ce framework à la mode), c'est un peu programmer volontairement de potentielles failles dans la carapace que l'on veut justement renforcer.
    Du coup, à chaque fois qu'on veut utiliser un framework, on va prendre son code source et en plus d'un audit de sécurité, on va se retaper l'intégralité du boulot de QA pour traquer le moindre bug résiduel sur toute la base de code du framework ? Qui peut se permettre de faire ça ?

    Plutôt que "ne jamais faire confiance à rien", est-ce que ça ne serait pas "faire une confiance éclairée à des acteurs connus et reconnus" la bonne approche ?

  5. #65
    Membre averti Avatar de marts
    Inscrit en
    Février 2008
    Messages
    233
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 233
    Points : 425
    Points
    425
    Par défaut
    Un bon exemple d'application de la programmation défensive est le langage Javascript. Ca montre aussi que le concept ne date pas de la dernière pluie.
    A l'origine Javascript s'appelait Livescript, et était conçu pour administrer des serveurs. Il a été pensé de façon à toujours se débrouiller pour renvoyer un résultat. Cette philosophie explique beaucoup de fonctionnalités du langage (qui par ailleurs ont été souvent critiquées). Par exemple :
    - pas d'erreurs liées à la non déclaration d'une variable (toute variable a par défaut la valeur undefined)
    - pas d'erreurs liées aux opérations arithmétiques "interdites" (la racine carrée de -1 donne la valeur NaN, une division par 0 donne la valeur Infinity, ... )
    - pas d'erreurs liées aux types des opérandes (il y a un cast implicite quand on additionne un nombre et une chaine de caractères, ...)
    ...
    11001.00101.10010.10000.00111

  6. #66
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par Luckyluke34 Voir le message
    Donc ce n'est pas de la programmation défensive à proprement parler... mais c'est le premier échelon de la programmation défensive ? J'avoue que j'ai du mal à comprendre là. En tout cas, ça n'aide pas à donner une définition plus claire.
    (D'après les précédents messages) La programmation défensive c'est s'assurer que les données venant de l'"extérieur" soient valides, ou à défaut ne casse pas le logiciel (ou sa "logique"/ sa mécanique, parce qu'un programmeur ne peut pas coder tous les chemins mine de rien et doit en supprimer).

    Nous, nous étendons cette définition avec l'"intérieur" c'est à dire le logiciel (ou la plateforme) afin de détecter le plus tôt possible les problèmes, les effets de bords ou autres, de façon la plus précise possible (par exemple avec la pile des appels, une énumération pour situer le code fautif, ...) et de la même façon que la programmation défensive (alerte, alerte pop-up, log, ...)
    Surtout que souvent, derrière le programmeur (ou les programmeurs) il n'y a [quasi] personne qui teste et/ ou l'environnement de développement est très réduit.

    Citation Envoyé par Luckyluke34 Voir le message
    Du coup, à chaque fois qu'on veut utiliser un framework, on va prendre son code source et en plus d'un audit de sécurité, on va se retaper l'intégralité du boulot de QA pour traquer le moindre bug résiduel sur toute la base de code du framework ? Qui peut se permettre de faire ça ?

    Plutôt que "ne jamais faire confiance à rien", est-ce que ça ne serait pas "faire une confiance éclairée à des acteurs connus et reconnus" la bonne approche ?
    Ce qu'il faut comprendre c'est qu'un framework, il y a des milliers de développeurs qui l'utilisent tous les jours, et ceci depuis X années.
    Donc un framework est utilisé quasi à 100% dans différentes situations/ différentes plateformes et si les développeurs reportent les erreurs, le framework devient de plus en plus fiable.

    PS: je parle des frameworks recommandés, pas d'un code source X sur github

    Alors que ton bout de code, il peut être le meilleur du monde, il n'y a que toi (ou ta société) qui l'utilise.
    Et plus il est gros, plus il est difficile de le tester dans toutes les situations, tous les cas, toutes les plateformes.

  7. #67
    Nouveau membre du Club
    Profil pro
    Programmeur
    Inscrit en
    Février 2007
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Programmeur

    Informations forums :
    Inscription : Février 2007
    Messages : 9
    Points : 28
    Points
    28
    Par défaut
    Bonjour,

    Je ne sais pas si cela est inclu dans la notion de la programmation défensive mais je m'efforce de bien contrôler les arguments de chaque méthode ou fonction de telle sorte de refuser à l'entrée toute valeur qui entraînerait un disfonctionnement du code (production d'un résultat ou d'un état incohérent, génération d'une exception, ...), de même je m'efforce de tester les valeurs retournées par les fonctions ou méthodes appelées (en outre il convient de détecter les valeurs "nulles" et les retours sur exception). Ces détections d'anomalies doivent s'accompagner de génération de messages d'erreurs explicites et souvent de retours vers l'appelant dans un état et une valeur de retour déterminés dans la description de la fonction ou de la méthode. Un bon programme doit bien réagir aux situations exceptionnelles en restant en toute situation dans un fonctionnement prédictible et en produisant, si une intervention humaine est nécessaire, les informations nécessaires à l'analyse de la situation rencontrée. Après une anomalie de fonctionnement d'un programme, si vous êtes amenés soit à devoir ajouter des "logs", soit à devoir tenter de reproduire le cas en mode "debug", soit tout simplement dans l'impossibilité d'identifier l'origine du problème et/ou dans l'impossibilité de le reproduire c'est sans doute parce que le programme n'a pas été conçu en intégrant une approche défensive. Lorsque l'on programme on devrait constamment s'interroger sur ce qui pourrait aller mal et essayer de s'en prémunir (ou d'en diminuer les effets néfastes) au lieu de ne penser qu'aux cas bien identifiés dans les spécifications techniques ou fonctionnelles. Ce qui rend la programmation compliquée c'est la multiplicité de la combinaison de tous les cas pouvant se produire. Lorsque aux plus bas niveaux de notre programme on adopte des principes simples et bien décrits (comme par exemple, de refuser les arguments incohérents et/ou de signaler ces cas), cela peut grandement faciliter l'exploitation et la maintenance du programme. Bien sûr adopter une approche défensive peut engendrer des coûts de développement supplémentaires. Avec l'expérience, avec l'acquisition de réflexes ce coût supplémentaire se verra progressivement réduit.

    Cordialement,

    André

  8. #68
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Pour info, le billet avait été vivement critiqué sur reddit. Notamment pour la partie faites confiance aux frameworks et n'utilisez pas de framework...

    Bref.

    Le problème avant tout est de définir ce qu'est la programmation défensive. Typiquement je ne range pas "se défendre contre des données pouvant être bidons" comme de la Prog Def. Je range ça dans "faire son boulot correctement".

    Je range en revanche: "ne pas faire confiance aux développeurs (les autres et nous aussi)" dans la programmation défensive. L'objectif que je lui donne est de résister aux erreurs de programmation. Les erreurs de contexte, c'est des erreurs auxquelles il faut s'attendre. Après, je ne suis pas dans un monde de sites exposés que des malotrus voudront pirater en exploitant les failles. Je suis plus proche du monde des systèmes critiques (avec des vies physiques en jeux). L'entrée externe pourrie, ce n'est pas une aberration qui doit pouvoir tout crasher, c'est un cas de figure à prévoir: les données externes ça se valide, point! Après je ne suis pas en embarqué non plus où l'on peut parfois vouloir prendre en compte des perturbations de bits pour raisons d'ondes électromagnétiques ou autre -- il y en a qui se posent se genre de question.

    (fail-fast pour relancer ou partir sur un système redondant, ou pas fail-fast pour rester en vie, c'est encore un autre sujet)


    Si je reprend cet exemple (que j'avais utilisé dans mon blog et qui a été repris sur dvpz), ceci est de la programmation défensive: les fonctions qui auraient dû avoir des contrats stricts (ici: "exige n >= 0 sinon undefined behaviour + baffes au développeur qui s'en sert mal"), ont des contrats élargis ("exception de logique si n <= 0").
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // C++, des fois que ma signature laisse planer un doute
    double my::sqrt(double n) {
        if (n<0) throw std::domain_error("Negative number sent to sqrt");
        return std::sqrt(n);
    }
     
    void my::process(boost::filesystem::path const& file) {
        boost::ifstream f(file);
        if (!f) throw std::runtime_error("Cannot open "+file.string());
        double d;
        while (f >> d) {
            my::memorize(my::sqrt(d));
        }
    }

    La version sans programmation défensive, mais correcte:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    double my::sqrt(double n) {
        assert(n>=0 && "sqrt can't process negative numbers");
        return std::sqrt(n);
    }
     
    void my::process(boost::filesystem::path const& file) {
        boost::ifstream f(file);
        if (!f) throw std::runtime_error("Cannot open "+file.string());
        double d;
        for (std::size_t l = 1 ; f >> d ; ++l) {
            if (d <= 0)
                throw std::runtime_error(
                    "Invalid negative distance " + std::to_string(d)
                    +" at the "+std::to_string(l)
                    +"th line in distances file "+file.string());
            my::memorize(my::sqrt(d));
        }
    }
    Pour moi ce second exemple n'est pas de la programmation défensive. C'est "juste" un programme correct, avec un zeste de Programmation par Contrat, et qui en plus retourne un message d'erreur exploitable.

    Sur le sujet, il y a un autre billet d'Andrezj AvecUnPatronymeQueJ'aiEncoreOublié où il pose un sondage pour savoir ce que les gens définissent par "programmation défensive", que l'on n'a pas encore traduit je crois: https://akrzemi1.wordpress.com/2015/...e-programming/ (AMA, il aurait fait un sujet de départ de dépêche bien plus sérieux que celui de l'évangéliste PHP)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  9. #69
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 377
    Points
    20 377
    Par défaut
    Citation Envoyé par foetus Voir le message
    Alors que ton bout de code, il peut être le meilleur du monde, il n'y a que toi (ou ta société) qui l'utilise.
    Et plus il est gros, plus il est difficile de le tester dans toutes les situations, tous les cas, toutes les plateformes.
    tout dépend par ce que l'on entend par Framework ?
    Dans le contexte de ce fil de discussion apparemment on parle de framework générique comme par exemple boost pour le C++ (ou NET...)
    A opposer à des frameworks spécifiques donc sensé géré des composantes par exemple métiers d'un projet logiciel

    Un outill comme boost par exemple ça peut être vraiment utile dans certains cas..parce que Boost c'est un outil sensé apporté la généricité.
    Donc on va opposer généricité versus spécificité et le bout de code dont tu parles parfois il fait des choses très spécifiques qu'un framework ne peut pas toujours faire.

    pour écrire une banalité, un projet informatique c'est un assemblage de composantes spécifiques et génériques reste à voir le degré d'utilisation de chacune....

    Le degré de spécifité ou de généricité des modules ( si on éclate un projet informatique en modules ) ça se fait à l'analyse et à l'architecture du projet.

    Maintenant un projet informatique qui n'est qu'un assemblage excessif de frameworks et technos existantes comme un jeu de legos , d'un point de vue économique n'apporte pas beaucoup de valeur ajoutée et pire que ça il risque d'être copié et cloné par la concurrence

    Citation Envoyé par Luckyluke34 Voir le message
    Qui vient en contradiction totale avec "don't reinvent the wheel", puisque si on ne fait pas confiance au code de ses propres collègues, on va encore moins réutiliser des librairies tierces, hein...
    là on fait du hors-sujet, ne pas faire confiance au code de ses propres collègues ça s'explique pour des raisons toutes bêtes :
    -méthodologie inexistante dans l'entreprise et les équipes
    -finalités du projet mal comprises de l'équipe de développement
    -pas de règles de codage...bref ça revient au point numéro pas de méthodologie
    -architecture du projet défaillante

Discussions similaires

  1. Réponses: 0
    Dernier message: 10/08/2011, 11h19
  2. [Système] quelques mot-clés pour apprendre
    Par aspo dans le forum Langage
    Réponses: 2
    Dernier message: 07/02/2007, 15h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo