C'est un compromis. Laissez-moi donner un exemple. J'ai découvert la technique de l'exécution différentielle vers 1985, et je pense que c'est un outil vraiment efficace pour la programmation des interfaces utilisateur. Fondamentalement, cela prend des programmes structurés simples comme ceci:
void Foo(..args..){
x = y;
if (..some test..){
Bar(arg1, ...)
}
while(..another test..){
...
}
...
}
et manipule la structure de contrôle comme ceci:
void deFoo(..args..){
if (mode & 1){x = y;}
{int svmode = mode; if (deIf(..some test..)){
deBar(((mode & 1) arg1 : 0), ...)
} mode = svmode;}
{int svmode = mode; while(deIf(..another test..)){
...
} mode = svmode;}
...
}
Maintenant, une bonne manière de faire aurait été d'écrire un analyseur syntaxique pour le C ou pour le langage de base, puis parcourir l'arbre syntaxique pour générer le code que je veux. (Quand je l'ai fait en Lisp, cette partie était facile.)
Mais qui veut écrire un analyseur syntaxique pour le C, le C++, ou quoi que ce soit d'autre?
Alors, au lieu de cela, j'écris simplement des macros pour pouvoir écrire le code de cette manière:
void deFoo(..args..){
PROTECT(x = y);
IF(..some test..)
deBar(PROTECT(arg1), ...)
END
WHILE(..another test..)
...
END
...
}
Cependant, lorsque je le fais en C#, quelqu'un a décidé que les macros étaient mauvaises, et je ne veux pas écrire un analyseur pour le C#, donc je dois générer le code manuellement. C'est une vraie douleur, mais ça en vaut toujours mieux que la façon habituelle de coder ces choses.