Styles

jeudi 31 juillet 2008

How to convert a file to a specific coding system without the help of iconv

I've once had a problem with coding system. I inadvertently inserted an euro (€) sign into a classic (Unix) buffer, and when I asked emacs to save it, it told me that the coding system I was using was not able to save correctly my buffer.

I saved it using UTF-8, but after that, when I opened the file, Emacs was unable to guess that it was UTF-8.

I found a little command set-buffer-file-coding-system that you can call by C-x RET f that allow me to specify which coding system I want to use for the current buffer and file. This is not like reverting to a specific coding system, no, emacs is really converting the file and each and every character in it to the coding system I want.

That way, I then save the file with the correct coding system, emacs having done the conversion.

mercredi 30 juillet 2008

Les vues et le contrôle d'accès fin aux données

La caractéristique principale d'un développeur est la fainéantise ! Si un développeur n'est pas assez fainéant, il ne se préoccupera pas de minimiser le nombre de lignes de code qui lui sont nécessaires.

Dans le cadre des systèmes d'information, il existe un moyen important à maîtriser pour réduire un maximum le code source redondant, comme le code source servant à vérifier l'accès aux données qu'a le droit de voir l'utilisateur. Nombre d'applications sont complètement sclérosées par du code dupliqué, répété à chaque fois qu'un accès à lieu à la base de données.

Un développeur orienté programme aura tout de suite envie de parler Programmation par Aspect, alors qu'il y a pourtant une méthode bien plus simple et d'ailleurs bien plus éprouvée.

Quand les utilisateurs d'une application ne doivent être autorisés qu'à consulter et modifier qu'une partie des informations existante en base de données, le plus simple est de créer des vues au dessus des tables contenant les données. Cela permet :
- d'encapsuler la logique de sécurité à un seul endroit : la vue

- de masquer la logique de sécurité au code source, permet ainsi de rendre l'application indépendante de la logique de sécurité

- de changer de logique de sécurité sans se soucier des impacts au niveau du code source de l'application.
La vue est un concept très simple à comprendre, mais si peu utilisée malheureusement ! Il n'est pas rare de retrouver le même code alambiqué recodant la même logique de sécurité (la clause WHERE de chaque requête SQL). C'est souvent le cas pour MySQL, car ce SGBD n'offre pas toutes les caractéristiques que l'on attend des vues.

J'ai cherché comment coder proprement avec MySQL, un système de gestion des droits fins d'accès au données, comme on peut le retrouver classiquement dans des systèmes de gestion de bases de données "sérieux". J'en ai fait un article : MySQL 5.0 Fine-Grained Access Control (FGAC).

On peut voir sur le site mysql.com que la notion de Fine Grained Access Control n'est pas comprise dans son acceptation la plus courante. Chez MySQL, elle se contente d'aller jusqu'au contrôle d'accès au niveau des colonnes. Mais quand on parle de Fine Grained access control, on pense à un contrôle d'accès au données au niveau de la ligne ("row level security").

Le contrôle d'accès au niveau ligne peut s'implémenter dans à peu près tous les systèmes offrant des vues, même si certains "se la pètent" plus que d'autre comme SE-postgreSQL :
"Only a few commercial DBMS products provide such functionality."
Euh... non. Même sur PostgreSQL (pas SE-PostgreSQL) on peut le faire avec un système similaire à celui que je propose dans mon article. PostgreSQL est beaucoup plus propre que MySQL au niveau des vues, l'implémentation du FGAC est moins tordue.

Le choix d'un système de vues pour contrôler comment l'application voit des données est une décision qui doit être prise au moment de la conception. Il est intéressant de définir clairement quelles sont les vues, et notamment, dans le dossier de politique sécurité, comment est implémenté le contrôle d'accès fin aux données.

Les vues se retrouvent plus ou moins dans tous les systèmes de gestion de bases de données, avec beaucoup de variantes, SQL ayant certainement la palme de la norme la moins suivi au monde :)

samedi 26 juillet 2008

Les mises à jour perdues sont trop souvent perdues

Il est assez honteux de voir encore aujourd'hui des applications Web ne pas traiter les problèmes de mises à jour perdues ("lost updates"). Ce problème est vieux comme le monde, des solutions plus ou moins complexes existent, et pourtant, cela n'empêche pas de le retrouver dans beaucoup d'applications de type concurrente et même dans les frameworks récents comme Grails par exemple.

J'ai rarement vu des dossiers de conception parler explicitement du problème et des solutions choisies. C'est pourtant une des rares choses à étudier.

Pour rappel donc, voici le scénario de ce problème :

Sur une application concurrente (comme le sont toutes les applications Web) :
- une session 1, lit l'information A
- une session 2, lit l'information A
- la session 1, met à jour l'information A
- la session 2, met à jour l'information A
La session 2 va écraser les mises à jour de la session 1 sans s'en apercevoir !

Ce problème arrive dès qu'une information est gérée concurremment (par plusieurs personnes en même temps).

Le problème est très bien explicité dans Expert Oracle Database Architecture de Tom Kyte.

La première chose à faire quand on construit une application Web, c'est de déterminer quelles sont les informations qui risquent d'être mises à jour par plusieurs personnes en même temps.

Ce ne sont pas toutes les informations qui sont accédées en même temps. Même si plusieurs utilisateurs accèdent à la même table en même temps, il se peut que par conception, il soit impossible aux uns d'écraser les données des autres.

Ensuite, on peut utiliser plusieurs méthodes pour empêcher le problème des mises à jour perdues:

- sérialiser tous les accès à l'information (on empêche d'accéder et mettre à jour une information tant qu'elle est en train d'être prise en charge par quelqu'un) : cela revient à mettre un verrou sur l'information, on perd alors tout l'intérêt d'une application concurrente.

- mettre un marqueur sur chaque information pour signifier à quelle date l'information a été mise à jour pour la dernière fois. Concrètement, si l'information est stockée dans une base de données, il s'agit de rajouter par exemple une colonne LAST_MOD contenant la date de dernière modification.

Avant chaque mise à jour, il doit y avoir une vérification que la date de dernière mise à jour LAST_MOD n'est pas plus récente que la date LAST_MOD existante lors de la lecture de l'information. Le scénario se déroule alors comme suit :
- la session 1, lit l'information A et le date LAST_MOD (last_mod1)

- la session 2, lit l'information A et le date LAST_MOD (last_mod1)

- la session 1, vérifie que LAST_MOD n'est pas plus récent que last_mod1. Ce n'est pas le cas donc l'information A est mise à jour, la date LAST_MOD contient maintenant la date à laquelle session 1 a mis à jour l'information (disons last_mod2),

- la session 2, vérifie que LAST_MOD n'est pas plus récent que last_mod1. C'est le cas puisque LAST_MOD en base vaut last_mod2 qui est plus récent que last_mod1. Le problème doit être alors remonté à l'utilisateur (par exemple, un message l'avertis que l'information A a été mise à jour depuis qu'on lui a présenté.)
- Le problème de LAST_MOD c'est qu'on n'est pas sûr à 100% qu'il n'y ai pas de mise à jour exactement au même moment par rapport au système. Si la précision de LAST_MOD est la seconde, il peut arriver le cas où les deux mises à jour se passent dans la même seconde. Le cas est rare il est vrai mais peut exister. Pour pallier à ce problème, il faut recourir à une valeur unique, calculée en fonction de la valeur de l'information. On calcule donc une chaîne de hachage et on la gère comme LAST_MOD (dans une colonne HASH par exemple)

- On peut ne pas vouloir bloquer les mises à jour quand ce n'est pas la même colonne qui est mise à jour. Pour une ligne dans une table de base de données, il y a plusieurs informations. Parfois deux utilisateurs veulent mettre à jour en même temps la ligne mais pas la même colonne de cette ligne. Ainsi, avec LAST_MOD ou HASH, on s'assure qu'il n'y a pas de mise à jour de toute la ligne en même temps. Mais il peut être intéressant de stocker les valeurs de chaque colonne de la ligne dans la session de l'utilisateur et de les comparer à celle de la base avant de faire la mise à jour.

On met à jour seulement les informations qui ont changées, le risque de mise à jour perdu diminue puisque la probabilité de mettre à jour la même colonne de la même ligne en même temps est plus faible. Cela permet d'être moins sensible aux mises à jour perdues et de remonter moins de problème à l'utilisateur.

Quelque soit la méthode employée, il est important d'en choisir une et de s'y tenir pour l'ensemble de l'application, pour qu'il soit plus facile de la maintenir. La méthode doit bien sur être explicité dans le dossier de conception.

Il faut bien garder à l'esprit que le problème des mises à jour perdues peut se produire pour n'importe quelle information, pas seulement en base de données. Dès que les données sont partagées (dans un fichier, en mémoire...), il faut faire attention aux utilisateurs qui vont les mettre à jour.

Parfois même un seul utilisateur peut perdre ses mises à jour s'il ne fait pas attention à ce qu'il fait sur chacun de ses écrans :)

mardi 22 juillet 2008

Surqualification en SSII, les ingénieurs analystes programmeurs

C'est un peu triste à constater mais la majorité des informaticiens professionnels ne développe que des applications Web. Aujourd'hui nombreux sont les ingénieurs informatique qui, dans les SSII (j'en ai fait parti) n'effectue qu'un travail d'analyse et de programmation.

Ce profil s'appelle l'analyste-programmeur, et c'est ce que, normalement, on est 2 ans après le bac avec un DUT Informatique. Il n'y a rien qu'à voir les débouchés cités sur la plaquette de l'IUT Lyon par exemple, pour s'apercevoir que c'est exactement ce que font des milliers d'ingénieurs en SSII.

Les applications de Système d'Information ne nécessite qu'un profil d'analyste programmeur pour correctement modéliser l'information et la mettre en œuvre. Dans les branches dites d'Intégration ou de Système d'Information, les SSII ont finalement peu recours à la formation de leurs employés. L'analyse du Munci sur le malaise en SSII est assez flagrant :
Bien souvent, les jeunes recrues des SSII, qui n’ont connu que ces sociétés (et qui ne connaitront peut-être qu’elles), qui plus est dans un contexte conjoncturel qui leur est favorable, n’ont pas encore conscience de tous ces problèmes (quelques années sont généralement nécessaires pour y voir plus clair...) : beaucoup font preuve d’une certaine naïveté (pour ne pas dire une certaine suffisance) par manque de repères et de comparaisons possibles. Et c’est ainsi que toute une génération, plus ou moins résignée, subit progressivement une mise en condition dictée par le "moins-disant professionnel"...
Beaucoup de problèmes d'organisation du métier d'informaticien semblent liés à la jeunesse des acteurs, à leur naïveté (j'ai été moi même très naïf sur le métier d'informaticien). Si jeunesse savait, si vieillesse pouvait :) Le problème c'est que les vieux informaticiens se font rare, ou sont au chômage...

vendredi 18 juillet 2008

Sortir du monde XML

XML, c'est bien connu, est verbeux à outrance. L'objectif initial de XML était de permettre de rendre lisible par un humain les données structurées. Cela présuppose qu'avant XML, les données n'étaient pas lisibles.

Perso, je préfère lire du CSV ou équivalent (comme par exemple les fichiers de conf sous Unix comme httpd.conf) plutôt que du XML. Certains vont même jusqu'à considérer XML comme un fichier binaire dans lequel il ne faut jamais regarder et qu'on n'utilise qu'à travers des outils.

Ce n'est pas étonnant qu'on en soit arrivé là sachant que la plupart des promoteurs des technologies XML et associées (je pense surtout à SOAP) sont des éditeurs d'outils qui ont tout intérêt à ce que XML ne soit pas lisible facilement par un être humain normal, et qu'on soit obligé de passer par un outil pour le manipuler. Ces éditeurs sont toujours les même : Microsoft, IBM en tête.

Non, XML et sa complexité inhérente, n'est pas issu d'un besoin client. Des formats simples comme le CSV par exemple ont été mise en oeuvre avec succès depuis très longtemps sans aucun problème d'incompatibilité. Quand une application doit gérer des flux importants, même avec nos serveurs surpuissants et nos réseaux terabytes, nous n'avons pas assez de bande passante pour supporter la verbosité d'XML.

C'est pourquoi de nouveaux formats sont apparus à la suite d'XML, car c'est bien connu en informatique, comme dans l'industrie de la mode vestimentaire, une nouvelle technologie rend, au yeux du public, les anciennes technologies ringardes et dépassées :
Les outils de développement logiciel et les technologies de l'information en général, partagent ces traits communs avec l'industrie de la mode vestimentaire:

- elle préfère des employés jeunes,

- elle change souvent,

- ce qui est vieux est "repackagé" en quelque chose de nouveau après une décade ou deux,

- la preuve de la supériorité de cette Nouvelle Chose n'est pas vraiment attendue
On peut noter que malgré ça, le CSV à toujours de beaux jours devant lui. JSON est apparu suite à l'émergence des applications Ajax.

Mais c'est maintenant Google qui se met à rendre public le format d'échange de données qu'il utilise partout en interne (justement parce qu'XML est trop lourd). Il s'agit de Protocol Buffers.
Ce nouveau format fait beaucoup de bruit, on peut lire un article de Ted Neward sur le sujet.

Face à XML, on voit donc tout un front de nouvelles technologies qui visent à remplacer la génération des protocoles et technos XML décadente, tellement encrée dans les années 90 :) :
- JSON
- Protocol Buffers
- REST
- Flex & consort
- YAML
- ...

Avec ces "nouvelles" technologies, on est toujours en face d'une guerre sans merci pour se disputer le marcher juteux de l'IT. Mais est-ce pour le bien de l'humanité ? :)

mardi 15 juillet 2008

Insert random Japanese Hiragana to overlearn them

Here are some functions I wrote to create a page of random hiragana for me to exercise for character recognition. The main goal is to learn to recognize quickly hiraganas and pronunce them correctly. As hiragana are written in a random order, it's not an exercise for learning to read japanese :

(defun delnth (n l)
(if (zerop n)
(cdr l)
(let ((prev (nthcdr (1- n) l)))
(setcdr prev (cddr prev)))
l))

(defun random-insert (nb l)
(let ( (remaining (copy-sequence l) ) (inserted nil) (num -1) )
(while (> nb 0)
(while (and (> (length remaining) 0) (> nb 0))
(setq num (random (length remaining)))
(setq elem (nth num remaining))
(insert elem)
(setq inserted (cons elem inserted))
(setq remaining (delnth num remaining))
(setq nb (1- nb)))
(if (> nb 0)
(progn
(setq remaining inserted)
(setq inserted nil))))))

(defvar jp-hiragana '("か" "け" "き" "こ" "く" "じゃ"
"ぐ" "げ" "が" "ご" "ぎ" "と"
"て" "た" "お" "ひゃ" "あ" "え"
"い" "しゅ" "みゅ" "ぷ" "ぴゅ"
"ぱ" "ぺ" "ぴ" "う" "ぽ" "びゅ"
"じょ" "みょ" "ぴょ" "よ" "や"
"ゆ" "ひ" "ほ" "は" "へ" "きょ"
"ど" "で" "だ" "ちゃ" "しょ" "ぎゃ"
"つ" "りょ" "ぎょ" "め" "ま" "も"
"きゅ" "み" "む" "ちょ" "じゅ" "し"
"ひょ" "ぞ" "ぜ" "ざ" "ず" "づ"
"びょ" "ぎゅ" "ん" "る" "にゃ"
"れ" "ら" "ろ" "り" "ひゅ" "りゃ"
"に" "の" "な" "ね" "ぬ" "びゃ"
"りゅ" "じ" "ぢ" "ち" "わ" "を"
"ふ" "にゅ" "す" "そ" "さ" "べ"
"せ" "ば" "ぼ" "び" "ぶ" "みゃ"
"ぴゃ" "しゃ" "ちゅ" "にょ" "きゃ")
"List of all Japanese Hiragana with different sonorizations and
concatenated syllables")

(defun jp-insert-exo (nbchar)
"Print a page of Japanese exercice."
(interactive "nNumber of characters to print: ")
(random-insert nbchar jp-hiragana))
The function delnth returns the list with the nth element removed. Random-insert randomly insert elements of a list of strings or characters. The variable jp-hiragana bring together all hiragana including different sonorization, and syllable concatenation.

The function jp-insert-exo command insert the given number nbchar of hiragana into the current buffer.

One limitation is that hiragana are inserted on a line. One could enhance these functions to correctly write them from top to bottom and left to right.

We can imagine the same kind of thing for katakana or even kanji. This exercise is interesting when you start to learn kana. The goal is to overlearn the kana in order to be really at ease with them.

Print a page or two of them and now, let's practise Hiragana ! Just pronounce each hiragana loudly (or loudly in your head) one after the other.

lundi 14 juillet 2008

Un boufficiel de plus : le système d'exploitation

Il n'y a plus besoin de recherche sur les systèmes d'exploitation depuis les années 70. Comme nous le rappelle fort bien Linus Torvald :
Heureusement, je n'ai jamais senti de pression pour suivre les microkernels. L'université d'Helsinki fait de la recherche sur les système d'exploitation depuis les années 60, et les personnes là-bas, ne voient plus les noyaux des systèmes d'exploitation comme des sujets de recherche. En un sens, ils avait raison : la base des systèmes d'exploitation, et par extension du noyau Linux, sont bien connus depuis le début des années 70. Toute chose après ça a été, à un certain niveau, un exercice d'auto-gratification.
Les Un*x, Windows et autres systèmes d'exploitation, sont construits autour d'implémentations très similaires, voire même identiques. Notamment la couche réseau Windows, qui fut longtemps basée sur l'implémentation BSD et qui seulement récemment à été re-développée.

On peut se demander pourquoi redévelopper une couche réseau extrêmement éprouvée à tous les niveaux (performance, sécurité, etc.). En effet, il y a de grandes chances qu'on voit réapparaître des bugs critiques sous Windows qui ont déjà été résolus il y a longtemps sur la couche réseau BSD.

Mais c'est certainement pour implémenter les nouvelles spécifications IPv6, IPsec, MobileIPv6 (c'est d'ailleurs aussi l'objet du projet KAME sur BSD)

Mais je pense aussi que ça fait parti de la logique de ce boufficiel. Microsoft dispose d'un ensemble de programmeurs qu'il doit bien occuper à quelque chose sous peine de perdre la connaissance du fonctionnement interne de Windows ! En effet, le code de Windows n'est plus documenté et est donc difficile à comprendre. C'est ce que nous raconte Gene Michael Stover à travers son expérience à Microsoft :
Chez Microsoft, si vous voulez savoir comment utiliser une fonction de Windows, vous êtes censés lire le code source de cette fonction pour apprendre comme elle marche et comment l'utiliser.
Notre mémoire étant volatile, seules des personnes qui travaillent régulièrement sur ce logiciel peuvent continuer à comprendre celui-ci. C'est tout le problème. Microsoft ne peut pas réduire la voilure, ne peut pas réduire le nombre de développeur sur Windows sans risquer de perdre de la compétence.

Heureusement, ce problème se marie fort bien avec une disposition réelle des utilisateurs à préférer leurs souhaits à leur besoins, à s'enthousiasmer pour n'importe quelles nouvelles fonctionnalités, comme nous le rappelle Niklaus Wirth dans A Digital Contrarian Retires :
Les programmes fiables et transparents ne sont généralement pas intéressant pour un concepteur de logiciel. Les souhaits des utilisateurs comptent plus que leurs besoins.
L'informatique a donc encore de beaux jours devant elle, ... ainsi que les systèmes d'exploitation :)

jeudi 10 juillet 2008

Intellisense, ennemi de la pensée désirée ?

N'avez-vous jamais été embêté par Intellisense ? Ne sentez-vous pas qu'il vous bloque parfois dans votre créativité ? La preuve, dès que j'essaie d'envisager un appel à une nouvelle fonction, dès que j'appuie sur "Enter", j'ai le message désagréable suivant :


En fait, intellisense est incompatible avec la méthode de développement par pensée désirée. Mais qu'est-ce donc que la pensée désirée en informatique ? L'architecte parlera d'approche top-down, mais c'est assez réducteur et simpliste car faisant croire à un processus de conception rationel fonctionnant par décompositions successives.

Comme nous le raconte très bien Steve McConnell dans Code Complete 2, et que je vous traduirais ainsi :
La conception est un problème "perfide" (wicked). Horst Rittel et Melvin Webber définissent un problème comme "perfide" quand il ne peut-être clairement défini qu'en le solutionnant ou en solutionnant une partie de celui-ci (1973).
Bien que la conception soit un problème perfide, on peut adopter des approches qui permettent d'être créatif quand à la solution à apporter.

Une des méthodes les plus intéressante est l'approche de la programmation par la pensée désirée : vous codez des algorithmes, des routines, des classes selon ce qui est plaisant d'imaginer, en imaginant un monde idéal et en faisant abstraction (dans un premier temps) du réel, de ce qui existe et de ce qui reste à développer.

Ainsi, si vous désirez développer une application de gestion de contacts personnels, vous commencez par écrire un programme utilisant une API idéale de gestion de contacts :

ContactCollection.GetMyContacts() ContactCollection.GetMyProfessionalContacts()

Ce n'est qu'ensuite que vous pouvez vous pencher sur l'implémentation de chacune des fonctions GetMyContacts, GetMyProfessionalContacts(). Cet exemple est trivial et vraiment simpliste mais ce qu'il faut retenir c'est qu'une telle approche permet de s'abstraire des détails d'implémentation, ce qui promeut une architecture orienté "problème métier" plutôt que "problème technique".

C'est là ou intellisense peut poser problème pour le développeur distrait. Sans faire attention, intellisense pousse à utiliser ce qui existe déjà, à penser implémentation avant de penser modélisation.

Et voilà comment on en arrive à développer des applications sans séparation claire entre les responsabilités de chaque module. Intellisense peut être vraiment intéressant quand l'architecture est complète et clairement définie, mais il serait bien de pouvoir désactiver cette fonctionnalités quand on se met à réfléchir à une architecture indépendante de l'implémentation.

dimanche 6 juillet 2008

Goto implicites et structures de données

Qu’est-ce qu’on reproche à ce fameux GOTO ? D’être indiscipliné ? De semer l’anarchie dans le code source ? Oui, c’est vrai qu’il nous ramène en plein moyen-âge informatique, à une époque où on connaissait à peine la notion de routine. Aujourd’hui, il est rare de trouver explicitement des GOTO dans du code. Il y a eu et il y a toujours beaucoup de bruit autour de l'emploi du GOTO, mais franchement, la hache de guerre est depuis longtemps enterrée.

Mais est-ce qu’implicitement il n’y aurait pas des sortes de GOTO qui se cachent discrètement dans mon code ?

Les structures des données traitées par un programme, contraignent les algorithmes chargés de leur manipulation. L’utilisation de tableaux indexés contraint très peu les algorithmes, ce qui fait qu’il peu exister une organisation implicite, non visible des données contenues par un tableau.

Un programmeur sera donc tenté d'accéder directement à n'importe quel élément du tableau et ainsi, reproduit au niveau du code un flux de traitement non séquentiel, voire même aléatoire : un peu comme des GOTO !

Ainsi, des sortes de GOTO implicites mais bien présents (par exemple, l’inflation du nombre de if(), de switch() et de break sans parler des IF arithmétique qu'affectionne les programmeur en Fortran) dans les algorithmes peuvent être employés pour gérer les données d’un tableau.

Comment s’assurer que les développeurs d’un logiciel ne se mettent pas disséminer des GOTO implicites ? En leur interdisant d’utiliser des tableaux indexé et en les obligeant à employer de véritables conteneurs comme les ensembles (Sets), les piles (Stacks) et les files d’attentes (Queues). Ces conteneurs obligent à accéder de façon séquentielle à leurs éléments et évitent ainsi l’introduction de GOTO implicites.

A éviter donc toutes les méthodes du type Collection.toArray()... ces méthodes ont l'inconvénient d'exposer partiellement l'implémentation, de dénaturer la collection en question.

Ce qui nous ramène donc à l'analyse statique du code, avec les outils classiques que sont les outils OpenSource FindBugs et PMD pour le monde Java, mais aussi commerciaux comme le puissant Polyspace que j'ai utilisé une fois sur un projet, ou d'autres. Il n'existe pas de règles déjà définit pour empêcher l'utilisation de tableau bien que de nombreuses règles portent sur le mauvais emploi des tableaux à travers les classes.

Alors, prêt à jouer les dictateurs et empêcher tout emploi de tableau indexé ? Allez... j'accepterai peut-être un Array si c'est correctement justifié :) mais alors, je considerai ça comme un nouvelle dette technique.

mercredi 2 juillet 2008

Prévision de changement de besoin

La seule et unique constante dans l'univers c'est le changement. Il en va de même avec les besoins des utilisateurs, clients, maîtrise d'ouvrage d'une application. Comment faire pour suivre cette évolution à moindre frais. Bien que certains proposent de multiples techniques de "refactoring", l'objectif est de ne pas avoir du tout à refactorer.

On peut y arriver si on envisage comment l'application va évoluer au cours du temps. Oui, mais ... qui peut prédire l'avenir ? personne, en tout cas, pas moi. Pour essayer de limiter les dégâts et prévoir au maximum les changements à venir, la gestion des exigences a été pour moi ce qui m'a le plus permis d'avoir une approche rationnelle de la gestion et de la prévision du changement.

L'article de Wikipedia est clair sur le sujet :
En ingénierie, et plus particulièrement dans les procédures d'appel d'offres publiques et privées, les exigences sont l'expression d'un besoin documenté sur ce qu'un produit ou un service particuliers devraient être ou faire. Elles sont le plus souvent utilisées dans un sens formel dans l'ingénierie des systèmes et dans l'ingénierie logicielle.
et notamment, sur les différents types d'exigence :
- Les exigences métier qui décrivent le quoi dans les termes du métier. Elles décrivent ce qui doit être fourni ou réalisé pour produire de la valeur.

- Les exigences produit qui décrivent le produit ou le système à un haut niveau. Elles répondent aux exigences métier et sont couramment formulées comme les fonctionnalités que le système doit réaliser. On les appelle également exigences fonctionnellles ou spécifications fonctionnelles.

- Les exigences de processus qui décrivent le comment. Ces exigences prescrivent les processus que l'on doit suivre et les contraintes auxquelles on doit se conformer pour la réalisation du système. Dans ce cas, on trouve par exemple des exigences de sécurité, d'assurance qualité, ou de management.
Le découpage en exigences des besoins permet de mettre un nom (un identifiant) sur chaque besoin élémentaire, le but étant d'avoir une liste exhaustive.

Au delà de permettre dans un projet, un suivi de bout en bout des exigences, l'intérêt principal c'est de ne pas perdre le besoin client dans une foule de détails plus ou moins techniques. Cela permet notamment au client d'être plus confiant et de lui permettre de valider l'expression écrite de son besoin.

Une fois la liste d'exigences rédigée, apparaît alors la phase qui permet de se protéger contre les changements du besoin. C'est une phase d'assurance qualité qui vise à s'assurer que toutes les exigences respectent les propriétés suivantes:
- Nécessaires – Elles doivent porter sur des éléments nécessaires, c'est-à-dire des éléments importants du système que d'autres composants du système ne pourraient pas compenser.

- Non ambiguës – Elles doivent être susceptibles de n'avoir qu'une seule interprétation.

- Concises – Elles doivent être énoncées dans un langage qui soit précis, bref et agréable à lire, et qui de plus communique l'essence de ce qui est exigé.

- Cohérentes – Elles ne doivent pas contredire d'autres exigences établies, ni être contredites par d'autres exigences. De plus, elle doit, d'un énoncé d'exigence au suivant, utiliser des termes et un langage qui signifie la même chose.

- Complètes – Elles doivent être énoncées entièrement en un endroit et d'une façon qui ne force pas le lecteur à regarder un texte supplémentaire pour savoir ce que l'exigence signifie.

- Accessibles – Elles doivent être réalistes quant à aux moyens mis en œuvre en termes d'argent disponible, avec les ressources disponibles, dans le temps disponible.

- Vérifiables – Elles doivent permettre de déterminer si elles ont été atteintes ou non selon l'une de quatre méthodes possibles : inspection, analyse, démonstration, ou test.
Mais on peut aller plus loin pour se protéger des futurs changements : imaginer au moins 3 possibilités d'évolution pour chaque exigence.

L'important est d'identifier ces évolutions comme de nouvelles exigences internes. Selon l'état d'esprit de votre client ou donneur d'ordre, vous pouvez faire apparaître ces nouvelles exigences ou pas.

Lors de la phase de définition de l'architecture, il est donc alors possible de faire des choix informés qui permettent à moindre coût l'évolution de chaque exigence métier, et d'en faire un véritable suivi.

Il existe beaucoup de techniques permettant l'extensibilité et la personnalisation d'une architecture. Savoir à l'avance ce qui va changer permet de ne pas oublier de mettre en place ces techniques aux bons endroits et de renforcer la solution face à l'avenir.

Ce travail implique bien sur un surcoût, mais beaucoup moins important que de répondre à un changement d'exigence non anticipé. Dans le cas de société de service, le surcoût est inutile dans le cas de développement au forfait, mais devient beaucoup plus justifiable dans le cas de TMA où la rentabilité des contrats s'avère dépendant de la qualité de l'application.

Ce processus de prévision des changements du besoin peut être pondéré par la prioritisation de ceux-ci. Il peut être bien sur être plus qu'intéressant d'interroger le client sur chacune de ces évolutions possibles. Car finalement, c'est quand même lui le mieux placé pour répondre.