C'est encore un malentendu : avec une organisation adéquate, dans une équipe de 200 personnes, chaque développeur pourra travailler en solo sur un ou plusieurs fichiers.
Version imprimable
oui, et ton cerveau ?
Ce que veut dire ce truc "académique" (qui est quand même l'état des recherches en psychologie cognitive), c'est que, présenté avec un grand nombre d'informations, ton cerveau (pas le tien, celui de l'Homme en général ;)) ne retient vraiment que 7 informations.
Donc "trop d'information tue l'information".
C'est tout ce que je veux dire..
L'exemple donné par Zartan étant que il serait difficile d'appréhender un fichier de 20 000 lignes, je dis qu'il est tout autant, voire plus (car nettement moins structuré, les noms de fichiers étant moins explicites que les noms de méthode) difficile d'appréhender 4000 noms de fichiers pour savoir lequel ouvrir...
Mon expérience..
Voir ci-dessus.. Que ce soit l'exemple avec les classes et énormément de classes, ou que ce soit le fait d'être "bien organisé".
Prenons encore 2 exemples pour bien faire comprendre le concept :
- Déjà cité : 85 classes d'objets s'affichant. Trouver les méthodes d'affichage.
- Autre : 85 classes d'objets à charger depuis une BD. Trouver les méthodes de chargement.
Je maintiens que en général (mais cela dépend évidemment du découpage en module) si on a fait un module par classe cela va être un jonglage permanent pour comparer les différentes méthodes. Et il faudra avoir l'ensemble des fichiers ouverts.
Si on a fait un découpage fonctionnel, on aura peut-être les mêmes 85 méthodes, mais rassemblées dans 1 (2 avec les 2 fonctionalités ci-dessus) fichier(s).
C'est tout ce que je dis...
Absolument. C'est ce que je disais dans mes posts précédents..
:D
T'es capable de me dire comme ça ce que font ces 60 000 fichiers de la JDK ?? :aie:
Et tu as 1500 pages à lire avant de comprendre, ce qui est au moins aussi long et fastidieux que d'avoir à parcourir le fichier de 20 000 lignes... :P
Le débat est un débat général. Pré-supposer une organisation du travail est une aberration dans ce cadre, et donc baser des conseils sur une telle organisation supposée n'est pas un bon conseil, c'est tout...
Dans 99% des cas de notre travail, nous n'avons aucun contrôle sur l'organisation du travail , à moins que nous ne soyons le Chef du Projet (et encore), ou que l'on travaille tout seul..
Que tu recommandes ceci pour une oganisation du travail, soit.
Mais tu ne peux pas baser un conseil à des informaticiens "lambda" en te basant sur une organisation du travail particulière.
Sauf qu'avec les outils dont nous disposons tu n'as pas besoin de savoir où se trouve l'information (dans quel fichier). N'importe quel éditeur un minimum évolué sait où trouver ce que tu cherches.
Trop de couplage => mauvais design.Citation:
Je maintiens que en général (mais cela dépend évidemment du découpage en module) si on a fait un module par classe cela va être un jonglage permanent pour comparer les différentes méthodes. Et il faudra avoir l'ensemble des fichiers ouverts.
Quel est l'intérêt de savoir ce que font ces 60000 fichiers ? Est-ce que dans un projet de plusieurs millions de lignes tu es censé savoir ce que font chacunes de ces lignes ? Bah avec les fichiers c'est pareil (pour ce qui est de retrouver l'info, voir ma remarque ci dessus).Citation:
T'es capable de me dire comme ça ce que font ces 60 000 fichiers de la JDK ?? :aie:
Si le design est correct tu n'as pas à lire 1500 pages pour comprendre une fonctionnalité.Citation:
Et tu as 1500 pages à lire avant de comprendre, ce qui est au moins aussi long et fastidieux que d'avoir à parcourir le fichier de 20 000 lignes... :P
Pour moi rien ne justifie les monstres que tu décris dans un environnement de développement actuel (et déjà il y a 20 ans on disait de ne pas mettre plus de 25 lignes, la fameuse hauteur d'un écran, par fonction, donc ce n'est pas nouveau en soi).
C'était une manière polie d'indiquer que mes propos avaient été interprétés de travers.
Comme je l'ai indiqué précédemment tous les grands projets open source dont j'ai cité la métrique ont une moyenne de 500 lignes par fichiers : Linux, apache, MySQL, etc... je n'ai rien présupposé du tout car ces projets ont des centaines de développeurs travaillant dessus, je préfère donc avoir tort avec eux.
D'autre part j'estime qu'un source de 20000 lignes est une manière de coder archaïque, qui tient plus de l'obfuscation de code qu'une méthode de codage propre.
Un code propre est un code qui peut être compris d'emblée par un informaticien qui ne connait pas le projet ou bien qui n'y a pas touché pendant six mois ou plus. On en est manifestement très loin ici.
Les recherches systématiques font perdre du temps... Beaucoup de temps.
Sans parler du fait que plus tu as de fichiers, plus tu rallonges le temps de compilation total, ce qui est là aussi une perte de temps significative. Je ne parle même pas des pages de #include (ou équivalents) consécutifs qui sont de vrais nids à dépendances inutiles et à code tentaculaire... Isoler une fonction d'un peu haut niveau peut parfois devenir un vrai casse-tête.
Même un fichier include peut être codé proprement :
et dans le code appelant :Code:
1
2
3
4
5
6
7 #ifndef MONMODULE_H #define MONMONDULE_H /* les définitions */ #endif
Quant à la recompilation totale elle n'est pas censée arriver fréquemment, et n'est donc pas une perte de temps significative puisque le temps de recompilation d'un fichier de 500 lignes est largement inférieur au temps de compilation d'un fichier de 20000 lignes. Sans oublier que pendant que le fichier de 500 lignes est compilé, on peut en éditer un autre alors que pour un fichier de 20000 lignes on se tourne les pouces en attendant que ce soit fini.Code:
1
2
3
4 #ifndef MONMODULE_H #include "monmodule.h" #endif
J'ajouterai que les EDI modernes nous aident en analysant le code et en nous permettent de cliquer directement sur une fonction pour atteindre son source. Dans un fichier contenant plus de 100 fonctions cette fonctionnalité devient quasiment inutilisable, cela n'a d'intérêt que si la liste des fonctions apparaît à l'écran sans qu'on ait besoin d'utiliser trop souvent les ascenseurs, ce qui serait une perte de temps.
Il faut s'adapter à son environnement de développement et mettre à profit les facilités qu'il nous offre.
Ah ? Tu travailles en RAMdrive ? T'as un indexeur qui tourne en permanence en bouffant 10% du temps CPU de la machine ?
Moi, mon projet actuel, c'est 4 Go (oui, GIGAOCTET) de fichiers dans la vue compilée, et plus de 500 Mo de sources répartis sur environ 15.000 fichiers... Chercher là-dedans, c'est du masochisme primaire.
Ce qui ne change absolument rien si tu as 20.000 fichiers sources (CPP) qui le référencent : il sera lu, préprocessé et compilé 20.000 fois... Et les entêtes précompilés ne sont pas toujours utilisables pleinement.
EDIT : Et devoir inclure N #include pour chaque bout de fonction un peu évolué, c'est la porte ouverte au copier/coller abusif de la liste des #include, et donc à des dépendances entre modules qui ne devraient JAMAIS arriver...
Mais le temps de compilation d'un fichier de 20.000 lignes est largement inférieur au temps de compilation de 40 fichiers de 500 lignes...
Quant à la recompilation totale, elle DOIT être prise en compte, c'est aussi ce qui détermine en combien de temps on peut livrer une version, et dans tous les cas elle doit être faite plus que régulièrement... De préférence avant chaque mise en configuration pour éviter d'avoir une vue qui ne compile plus.
Donc, tous les jours, pour chaque développeur... Yahou, quand ça prends deux heures, non ?
Certes. Sauf que construire ce genre d'index prends là aussi du temps, requiert souvent une compilation totale auparavant (tiens donc... :mrgreen:) et qu'il est hors de question de balancer un fichier binaire de plus de 200 Mo directement en configuration, surtout quand il change tous les jours.
Sans être partisan du "fichier unique", l'hyper-séparation en fichiers contenant 3 lignes de code est tout aussi débile que de travailler sur un CPP unique incluant "en dur" tous les entêtes. Mais quitte à avoir une usine à gaz, je préfère celle qui se construit vite.
C'est un faux débat. Ce sont là des choix qui peuvent se défendre en termes de coût, d'efficacité ou de rapidité mais jamais en termes de "codage propre".
Je continue quand même à penser que la division en petits fichiers nous fait gagner du temps ;)
D'ailleurs si ce n'était pas le cas tous les grands projets auraient des sources de taille monstrueuse, et en ce qui concerne ceux auxquels nous avons accès cela n'est pas avéré.
Pas mieux, les seuls arguments avancés se résument à "quand c'est crade, vaut mieux que ce soit encore plus crade"...
Faire une recherche de méthode sous eclipse dans un projet (même très important) est quasi instantané... Et même s'il faut compiler une fois, ce n'est qu'une fois (et par défaut, sous eclipse, le projet est recompilé à la moindre modif, vive la compil incrémentale)... Donc oui, j'utilise un environnement moderne, et si ce n'est pas ton cas je compatis (et pas besoin de ramDrive).
PS : pour les include rien n'empêche de les encapsuler par modules...
Voici par exemple l'arborescence du Zend Framework un "petit" projet de 2000 fichiers (44Mo zippé), sur lequel une centaine de développeurs travaillent régulièrement.
Voyez comme c'est aisé de s'y retrouver, si demain je veux écrire un gestionnaire PDO pour une base de données non référencée je saurai exactement :
- où le faire en consultant rapidement l'arborescence
- quoi faire en m'appuyant sur les sources de 200 lignes des gestionnaires déjà écrits.
De plus une erreur éventuelle dans mon code ne mettra pas en danger ce qui a déjà été écrit, à l'inverse de ce qui se passerait si tous les gestionnaires de BDD partageaient un source commun.
http://img197.imageshack.us/img197/5889/zend.jpg
Ça l'est tout autant sur Visual ou Delphi...
Sauf qu'Eclipse est monstrueusement lent, bouffe trop de ressources à mon goût et la mise en configuration de l'environnement est quasi impossible (je hais ce répertoire ".metadata"...).
Quant à la compilation incrémentale... Certes, ça marche souvent. Et ça ne change absolument rien au fait qu'une compilation totale reste nécessaire dans plusieurs cas, ce qui implique donc un vidage intégral des fichiers générés (=vue propre), et recompilation complète.
Et alors ? Cela ne change rien au fait que l'élément basique de compilation en C/C++, c'est le fichier source, pas l'entête, et qu'à chaque nouveau fichier source, les entêtes sont de nouveau totalement compilés... Ce qui est une perte de temps si tu as à chaque fois 300 entêtes lus et compilés, surtout si certains ne contiennent presque rien.
Et, je le répète, les entêtes précompilés ne sont pas toujours utilisables, et/ou provoquent des dépendances inutiles.
Question de goût... Quelques niveaux de répertoires, OK, mais trop, ça devient franchement pénible.
Inversement, quand tu corriges un bug, tu n'es jamais certain d'avoir impacté tous les sources qui devraient l'être, ce qui provoque le phénomène amusant d'avoir le bug corrigé dans un cas d'utilisation et pas dans les autres...
Sans parler que certaines fonctions de haut niveau deviennent totalement impossibles à classer : une organisation aussi éclatée marche à peu près pour un framework, ça l'est rarement pour un système... Ne serait-ce qu'à cause des modules transversaux !!!
Et c'est là que tu te trompes, et lourdement en plus... Tu n'as qu'à voir les changelogs de beaucoup de projets open-source pour en être convaincu, ceux de Firefox sont de bons exemples justement : à chaque version, t'as la correction d'un problème que 99% des gens n'ont jamais vu, et qui arrive dans un cas vicieux donné... A chaque fois, tu avais une correction similaire dans les versions précédentes, dans un autre cas plus ou moins tordu.
Si tu as des "œillères" en regardant ton code, et que tu corriges par exemple le code de suppression d'une table sous MySQL, tu n'as absolument AUCUNE raison d'aller vérifier si c'est pareil avec Oracle ou SQLite. Je dirais même mieux : tu dois toujours toucher le moins de fichiers possibles pour conserver l'avantage d'une telle découpe... Et tu peux donc laisser le même bug non corrigé dans d'autres cas d'utilisation.
Ou tu peux oublier d'aller faire la même chose dans le module MySQL crypté, ou dans le générateur de requêtes, ou n'importe où ailleurs. Et avoir donc le bug dans certains cas de figures.
Si ton arbre de dépendances référence trop de fichiers, tu n'auras JAMAIS le budget alloué pour aller tous les vérifier, ça c'est également certain.
Avec quelque chose organisé différemment, c'est à dire moins éclaté partout, avec un minimum de partage de code et dans lequel les modules sont orientés macroscopiquement, tu ne touches qu'à quelques fichiers seulement, mais tu corriges le bug dans tous les cas de figure, tu répercutes la correction sur les modules similaires et tu peux plus facilement vérifier les dépendances pour les régressions.
En plus, c'est plus facile de faire un programme modulaire à haut niveau avec un découpage macroscopique des modules. Quand ta découpe est presque au niveau de la fonction, soit t'as un plat de spaghetti indémontable, soit tu finis toujours par ajouter du code mort (ou redondant) à ton programme.
Visiblement tu fais beaucoup d'amalgames dans tes propos. A la base de l'école que nous défendons ici sur le code propre, il y a le précepte "aucune duplication de code". Et c'est vraiment la base de la base.
Multiplier les fichiers pour de bonnes raisons ne signifie absolument pas dupliquer du code.
La duplication de code c'est le Mal.
Donc, en découpage "intensif" mais SANS duplication de code, tu as donc un joli plat de spaghetti... Ou des trucs tellement séparés les uns des autres (type framework) que tu n'as forcément aucune duplication de code.
J'suis vraiment pas certain de préférer ça à un code plus "condensé", tu vois...
Dans mon exemple, je n'ai pas à impacter les sources du pilote Oracle si j'écris le pilote MySQL. Si je dois faire quelque chose dont dépendent ces deux modules, par exemple rajouter une fonctionnalité commune, ce sera probablement dans le fichier Abstract, ou bien en créant un nouveau répertoire avec les classes adéquates.
Ca ne me pose aucun problème de gérer un module transversal de cette manière, par exemple un système de log peut tout à fait être contenu dans un répertoire à part, on n'a besoin que d'un nombre limité de fonctions à interfacer.
J'ai pris ici l'exemple d'un framework, mais j'aurai pu prendre à peu près n'importe quel projet open source un peu conséquent, que ce soit GCC, MySQL, apache, ou même le noyau Linux, et j'aurai retrouvé le même type d'organisation.
Des projets importants avec des fichiers sources extrêmement grands j'en ai vu, mais ceux-ci étaient l'oeuvre d'un seul programmeur, jamais le fruit d'un travail d'équipe.
Et sur un module réellement transversal, tu fais du code tentaculaire qui référence 200 modules... Et quand tu fais l'arbre d'impact de ta modification, tu pleures.
De plus, je le redis : un framework étant composé par nature de briques élémentaires, un tel découpage semble "beau et merveilleux"... C'est nettement moins le cas avec un projet plus conséquent implémentant des fonctions de bien plus haut niveau.
Et le même genre de changelog que j'ai cité avec Firefox : corrections de bugs arrivant dans des cas "pointus", et à la prochaine version ça sera encore le cas, comme c'était le cas à la version d'avant...
A chaque fois que j'ai ce genre de bugs, pour ma part, c'est à chaque fois dû à une fonctionnalité éclatée sur plusieurs fichiers, souvent de façon pas spécialement immédiate d'ailleurs. C'est bien plus rare sur un "gros" module dont les entrées / sorties sont, finalement, très simples quand on les regarde macroscopiquement.
Faut pas non plus exagérer sur le "extrêmement grands", mais faut pas non plus tomber dans l'effet inverse.
Quand supprimer une fonction se résume à enlever un répertoire et une liaison, c'est "modulaire".
Quand ça revient à supprimer N fichiers sources dans M répertoires et patcher K autres fichiers pour enlever la référence, ce n'est plus modulaire mais "tentaculaire"...
Mon cerveau ne se mets pas en kernel panique lorsque plus de 7 images, 7 textes ou 7 noms de fichiers/répertoires se trouvent dans mon champs optique, il faut arrêter de délirer une étude scientifique reste une étude scientifique c'est tout, l'interprétation qu'on en fait est relative, tu crois à cela de manière absolu ?
Est-ce que 8 c'est trop ? Est-ce que 9 aussi c'est trop et tue l'information ?Citation:
Donc "trop d'information tue l'information".
Bref nous nous éloignons de la propreté de code et comme dis précédemment on peut trouver des fichiers avec 20000lignes de code (ce qui peut faire un sacré bouquin de chevet) lisible et propre en tout cas en théorie mais à mon avis c'est le côté pratique de faire du code propre qui pose problème.
En admettant que j'ai ajouté un paramètre dans l'interface de mon module de log, là effectivement ça va atteindre tous les fichiers. Ceci dit je ne vais pas être sans ressources, et je peux probablement arriver à m'en sortir.
C'est un problème connu depuis plus de 20 ans, les techniques objets ont en partie été développées pour y pallier. C'est possible d'y remédier en C également, en suivant des règles de conservation assez simples.
peut être étendue en :Code:
1
2
3
4
5
6
7 #define INTERFACE_VERSION 1 struct alpha { int al_version ; /* éléments */ };
Ca revient à simuler de l'objet en C, la compatibilité avec l'ancien code étant préservée. Je peux donc ajouter autant de paramètres que je veux à partir du moment où je me sers d'un struct pour les interfacer. Les fonctions à paramètres variables sont une autre possibilité.Code:
1
2
3
4
5
6
7 #define INTERFACE_VERSION 2 struct beta { struct alpha be_alpha ; /* nouveaux éléments */ };
peut devenirCode:
1
2
3
4 log(LOG_FILE, "nomfic", LOG_MESSAGE, "hello, world", LOG_END) ;
Si un paramètre n'est pas indiqué une valeur par défaut lui est attribuée, garantissant encore une fois la compatibilité avec l'ancien code.Code:
1
2
3
4
5 log(LOG_FILE, "nomfic", LOG_MESSAGE, "hello, world", LOG_TIME, "18:00", LOG_END) ;
Ces techniques et d'autres encore permettent de concevoir ses interfaces avec soin.
Et quand les interfaces sont conçues avec soin l'extension n'est jamais un problème.
Il va sans dire que les méthodes offertes par la POO vont encore plus loin dans ce sens.
Le problème n'est pas "de s'en sortir" : c'est "juste" notre métier de savoir le faire.
Le problème, c'est de le faire vite, sans erreurs et en évitant de devoir revalider l'intégralité du projet jusque dans le moindre recoin... Ce que ne permet pas le code tentaculaire.
Tu comprends mieux ce que je veux te faire comprendre ?
Tout à fait, si les interfaces sont suffisamment robustes ça ne doit pas poser de problème. C'est effectivement tout le défi du code "tentaculaire" de créer des interfaces correctes.
absolument, mais de l'autre côté ce débat est sur "comment obtenir", pas sur "on a un code propre".. ;)
Bien sûr que non, mais la limite (même si ce n'est pas 7) n'en est pas moins réelle..
"Overload system"
L'exmple donné par Zartan est simplissime.. Que des choses de premier niveau...
Mais déjà, fonctionner au premier niveau avec 15 ou 20 répertoires indique déjà à mon avis une mauvaise conception.. Des répertoires comme "Ad" ou "Amf" ou "captcha" ne me disent rien du tout, un répertoire "application" !!! c'est pas ce qu'on est en train de regarder, une application ?? Et "crypt" ?? crypter quoi ? A quoi cela s'applique-t-il ?? et quelques autres...
Comme le dit Mac,
Mais qu'est-ce que tu crois ???
Que l'objet est la panacée ?? Que tous les "anciens" étaient c.ns ?
Un projet est un projet, quel que soit son langage !!!!
C'est marrant, on dirait une religion ou les communistes (ou ultra-libéraux, pour ne pas faire de jaloux :)): "avec l'objet, tous vos problèmes sont résolus" ...
LES PROBLEMES DES PROJETS SONT LES PROBLEMES DES PROJETS....
Un bon architecte en "procédural" fera un bon projet. Un mauvais architecte en objet fera un mauvais projet..
Faux..
Les 3 seules possibilités réelles et maintenables de faire quelque chose comme ça serait soit un #ifdef clair et précis :
car là au moins c'est clair et c'est limitéCode:
1
2
3
4
5
6
7 #ifdef VERSION_1 void toto (int A, int B) #else #ifdef VERSION_2 void toto (int A, int B, char *Login) #endif #endif
ou bien :
ou encore fonctionner par fonctions enregistrées...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 typedef union pValue { int iVal ; float fVal ; double dVal ; char cVal ; char $sVal ; } Value ; typedef struct pParam { int Type ; Value Val ; } Param ; typedef struct pMaStruct { int VersionNumber ; int NParams ; Param *MesParams ; } MaStruct ; void toto(MaStruct *MaMienne)
qu'on peut aussi décliner avec :Code:
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
36
37 /* Version */ void toto1 (void *Struct) { MaStruct *MaMienne=(MaStruct *)MaMienne ; int i,j ; i = MaMienne->A ; j = MaMienne->B ; } /* Version 2 */ void toto2 (void *Struct) { MaStruct *MaMienne=(MaStruct *)MaMienne ; int i,j ; char *MonLogin ; i = MaMienne->A ; k = MaMienne->B ; MonLogin = MaMienne->Login ; } ...... if ( Version1 ) RegisterFunction ( ACTION_TOTO, toto1 ); else if ( Version2) RegisterFunction ( ACTION_TOTO, toto2 ); .... if ( RegisteredFunction ( ACTION_TOTO ) ) { CallRegisteredFunction ( ACTION_TOTO, (void *)&MaStruct ); }
auquel cas tu peux avoir une version 1 et une version 2 sans changer quoi que ce soit à ton code d'appel... (pour peu que l'on ait placé les fonctions dans un seul module, ou que le module contenant la définiton de la fonction soit dans une biblothèque portant le même nom mais différente suivant le paramètre de link)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 void toto (void *Struct) { MaStruct *MaMienne=(MaStruct *)MaMienne ; int i,j ; i = MaMienne->A ; k = MaMienne->B ; if ( MaMienne->Version == 2 ) { char *MonLogin ; MonLogin = MaMienne->Login ; } } ...... RegisterFunction ( ACTION_TOTO, toto );
A éviter comme la peste....
Dès que tu reprends un code où les paramètres sont variables, le temps passé à comprendre ce qu'ils pourraient être, à quoi ils pourraient servir, et comment on pourrait s'en servir est bien plus lent que d'avoir 5 méthodes avec 5 interfaces...
Et comme je l'ai dit plus haut, un code tentaculaire peut tout à fait exister (et c'est même plus courant que le contraire) en objet..
:D
J'ai pas l'impression que ce soit le point de vue de Mac. En tout cas, travailler avec du code existant est toujours un problème. Dans tous les cas, commencer par du refactoring (dont l'extraction n'est pas un des moindres aspects) est fondamental. Après quand on intervient en mode pompier avec des délais pas raisonnable on n'a pas forcément le choix :( , mais ce n'est pas non plus la règle.
Jeune idéaliste... :mouarf:
Refactoring ? Sur certains projets, crois-moi, tu auras environ 2 minutes allouées au refactoring, le temps de descendre le projet depuis la gestion de conf.
Et après, tu seras (presque) aimablement prié d'arrêter de tripoter du code qui marche depuis des années, qui a fait ses preuves et en lequel le client a confiance par simple retour d'expérience. Et de te dépêcher d'ajouter la fonction pour laquelle on te paie...
Et même sur les projets que l'on démarre seulement, tu as toujours d'un côté les financiers qui réduisent ton budget de développement (sous la pression des commerciaux qui cassent les prix pour récupérer un marché), et de l'autre le client qui veut un truc répondant à son besoin.
Tu dois donc forcément sacrifier quelque chose pour tenir ton planning : au mieux, c'est la conception (et une pieuvre de code, une !), au pire, c'est la validation (et un projet sous garantie permanente, un !).
Et si vraiment c'est la cata, c'est les deux qui sautent... Essaie de demander 3 mois de dev pour refactoriser ça, tu verras bien comment tu seras reçu dans la plupart des boîtes. Ce n'est hélas pas le monde des Bisounours dehors, la concurrence est souvent féroce.
+1 avec Mac Lak.
Les seuls cas ou j'ai vu des gens pouvoir faire du refactoring, c'est quand ils étaient en position de force. Et c'est pas le cas classique. Il m'est arrivé d'en faire quand les délais étaient généreux, mais c'est l'exception, pas la règle.
Les captcha sont les mots déformés que l'on tape pour s'identifier sur un site web.
C'est faux, les méthodes que j'ai cité ont été mises au point dans les années 90. Elles ont été utilisées pour interfacer un système d'exploitation. Et cela fonctionnait très bien, des milliers de développeurs les ont utilisées, à chaque fois que le système évoluait, l'ancien code continuait à tourner.Citation:
Les 3 seules possibilités réelles et maintenables de faire quelque chose comme ça serait soit un #ifdef clair et précis
Ce qu'il faut éviter comme la peste c'est justement de citer les paramètres dans l'interface de la fonction, car cela empêche toute évolution.Code:
1
2 Dès que tu reprends un code où les paramètres sont variables, le temps passé à comprendre ce qu'ils pourraient être, à quoi ils pourraient servir, et comment on pourrait s'en servir est bien plus lent que d'avoir 5 méthodes avec 5 interfaces...
On peut également utiliser cette méthode recommandée par B. Meyer
Quelle que soit la manière de coder on est bien obligé de se demander ce qu'ils pourraient être et et à quoi ils pourraient servir. Perdre son temps en recherches dénoterait un manque d'outils de documentation.Code:
1
2
3
4
5 objet = new Objet() ; objet->setunparam(unparam) ; objet->setunautreparam(autreparam) ; objet->faitquelquechose() ;
Un outil moderne de documentation : http://www.javadoconline.com/search....n&class=string
Je n'ai pas dit refactoriser par plaisir. J'ai dit refactoriser là où on doit intervenir. Ca n'a rien à voir avec les délais ou je ne sais quoi, ça a à voir avec ta propre méthodologie pour travailler avec du code existant. Evidemment ça demande de la pratique et pour être efficace il faut pratiquer en dehors du contexte professionnel (au moins dans un premier temps).
Pour ce qui est des jugements de valeur à l'emporte pièce, à 4 mois prêts j'ai l'âge que tu affiches sur ton profil. J'espère que ça te fera méditer un peu ...
Et c'est surtout impossible de le faire "localement" dans un code tentaculaire, ce qui arrive souvent avec une débauche de fichiers...
Sans même parler que si tu es dans une structure un minimum rigide (=application de normes données), tu vas devoir justifier chaque ligne modifiée, et prouver que ça ne change ni l'implémentation, ni les E/S, et que ça continue de respecter la norme.
Je te signale quand même que certaines de ces normes interdisent strictement tout ce qui est pointeurs...
Tout a à voir avec les délais... A part en recherche / veille techno, aucune boîte censée ne te filera un budget illimité pour réaliser une action X ! Tu auras toujours, quoi qu'il arrive, une charge allouée (jours de devs) et une date butoir calendaire pour livrer.
Essaie un jour d'aller expliquer à un client que tu vas avoir un mois de bourre parce que t'as voulu te simplifier la vie, tout en expliquant au contrôleur de gestion pourquoi t'as 30 jours/homme de plus sur la balance et en esquivant la Qualité pour non-respect soit des normes, soit du processus de validation...
Une grosse partie de mon boulot est, justement, la remise à niveau d'ancien code vers des technos / normes / etc. récentes, ainsi que du portage / adaptation / stub de code.
Il n'y a RIEN dans le domaine privé qui puisse te préparer à certaines horreurs / conflits que l'on peut trouver dans le milieu pro "réel"... Sans même parler de la problématique du matériel (que tu n'auras pas à la maison) et qui t'empêchera de tester !
Je te passe bien sûr sur le code obscur que tu serais tenté de remplacer par une variante "propre", jusqu'à ce que tu te rendes compte que ça explose sur certaines plate-formes : j'ai déjà eu la farce avec un code de recopie très laid, remplacé par une copie "propre" qui avait la particularité amusante de crasher en "Bus error" sur des CPU Sparc... Le genre de bug assez mignon à retrouver, surtout en plein milieu d'une cascade de templates C++ imbriqués les uns dans les autres. Au final, obligé de remettre le code "laid", agrémenté toutefois de nouveaux commentaires expliquant le pourquoi du comment...
Quoi que tu dises, ta manière de voir les choses (idéaliste) est proche de celle des débutants (jeunes), lorsqu'ils n'ont pas encore pris conscience de certaines réalités et contraintes.
On peut avoir 60 ans et être "jeune" d'un certain point de vue, comme être "vieux" à 15 ans... Sur ce coup, tu es "jeune" parce que tu sembles penser que le refactoring, c'est simplement utiliser le menu contextuel d'Eclipse sur du code Java bien propre. Et ça, c'est vraiment la poussière au dessus de la partie visible de l'iceberg... Rassures-toi, t'es loin d'être le seul.
Une citation pour la route :
Quelle est la différence entre la théorie et la pratique ?
En théorie, il n'y en a pas. En pratique, si.
A méditer attentivement...
Je me base sur ce que tu écris, comme c'est l'usage et l'habitude sur les forums.
Prendre comme pré-requis un refactoring sur un code tentaculaire, c'est qu'on ne doit vraiment pas avoir la même notion de ce qu'est ce genre de code... Ou que tu n'as vu que des cas "légers" !! Je suis désolé, mais pour moi, ce que tu as écris est aussi idéaliste que de prétendre qu'on peut négocier ses dettes en devenant copain avec son créancier...
Quand à zapper les 3/4 de ma réponse pour te focaliser sur la dernière partie, c'est soit du troll, soit effectivement une attitude "jeune" car tu te vexes sur ce point précis.
;) on a déjà eu l'occasion d'en discuter avec Furikawari..
Il est très très très très très rare que l'on soit autorisé/que l'on ait le temps de faire du refactoring..
Et quand c'est le cas, c'est en général parce que l'application marche mais est très vieille, et qu'il n'y a plus la connaissance.. ni la documentation..
Donc on est hors sujet par rapport au thread, car le code qui était peut-être propre au début ne l'est quasiment certainement plus au bout de 5 ans, et ne parlons pas de 20 ou 30 ans......
Qui s'appeleront autrement dans 5 ou 10 ans, faisant perdre toute notion de ce que cache ce répertoire..
Admettons. Mais les OS sont un cas extrêmement particulier des applications...
On verra ce que tu diras quand tu tomberas sur un code comme ça, dans 15 ans... ;)
Très bien pour des nouveaux projets..
Mais, de toutes façons, quels que soient les projets et les outils, tu peux être absolument certain que si le soft dure un certain temps, dans 5 ou 7 ans la doc ne sera plus à jour, et dans 10 ans tu ne pourras peut-être même plus relire ce format...
Mmm, je pense pas. Le terme capatcha est bien assis aujourd'hui. D'une part parce que c'est un (retro)-acronyme et d'autre part une marque déposée par l'université Carnegie Mellon (cf wikipedia). Dans le futur, si le terme venait a ne plus être employé, il devrait continuer à faire parti de la culture générale.
Possible, mais ça reste un risque. Moi, si j'arrive sur ce projet(peu probable, c'est pas mon domaine, mais en SSII, sait-on jamais?), il faudra m'expliquer.
Et puis les termes changent, je me trimballe des données "POL" qui sont des numéros de contrats(avant c'était des polices), des "INTERM" ou des "GES" qui sont des numéros d'agents, des "FORMV" qui sont des tops impression.....tous ces termes avaient un sens clair un précis en 1972, mais moi, j'ai eu beaucoup de mal.
Mmm... en cherchant "Visual Cryptogram" sur internet, on tombe plus facilement sur le code à trois chiffres au dos des cartes bancaires que sur un test automatique de contrôle visuel d'une internaute humain.
Avec Captcha, on sait exactement de quelle fonctionnalité il s'agit.
Là vraiment, je ne te suis pas.
Change de moteur de recherche, moi je tombe bien sur une page correcte dans les premiers résultats... :mouarf:
On n'est jamais à l'abri d'un abus de langage. Ce code, normalement, est nommé CVV (Card Verification Value), ce qui n'a absolument rien à voir avec un "cryptogramme visuel"... Ce terme est par contre vastement employé sur le net pour les captcha, que ce soit sur les forums, les mails, etc. et ceci depuis bien avant l'utilisation massive du CVV.
Ceci étant dit, ça, encore, c'est un cas particulier. Le nommage type "Auth" ou "Crypt" est bien plus critique à mon sens... "Auth", c'est quoi ? Author ? Authentification ? Authenticator ? Authentifier ? Authority ?
Idem pour "Crypt", là aussi t'as des tonnes de possibilités rendant l'utilisation d'un simple "Auth" ou "Crypt" ambigu lorsque tu débarques sur ce genre de projet...
Juste une petite digression, qui ne change pas grand chose au fond du problème.
Non ce n'est pas si simple que ça.
Le terme CVV (en fait CVV2) est le terme employé par Visa. Mastercard utilise le terme de CVC2, American Express utilise CID, 4DBC ou CID/4DBC et le GIE Carte Bancaire emploie pour sa part effectivement plutôt le terme de cryptogramme visuel (mais les anglophones ne comprendront généralement pas le "Visual Cryptogram").