Il faut tout d’abord comprendre comment un code peut se modifier et muter en un tristement célèbre code spaghetti. Délais trop courts, manque d’expérience ou directives pas assez claires : en intégrant des instructions inutilement compliquées, la programmation d’un code entraîne des pertes de fonctionnalité. Plus son domaine d’application est rapide et complexe, plus la dégradation du code prend de l’ampleur.
Le terme code spaghetti désigne un code source brouillon et illisible, dont le langage de programmation est difficile à comprendre. Exemples simples de code brouillon : les sauts inconditionnels (goto) superflus, qui donnent l’instruction au programme de sauter d’un endroit à l’autre du code source. Citons aussi les boucles for/while et les instructions if superflues.
Ce sont particulièrement les projets auxquels participent de nombreux développeurs logiciels qui ont tendance à intégrer du texte source incompréhensible. Lorsqu’il passe entre plusieurs mains, et lorsqu’il contient déjà des faiblesses de départ, le code source intègre de plus en plus de liens prenant la forme de « solutions de contournement » : une révision du code dispendieuse est presque inévitable. Dans les cas les plus extrêmes, le code spaghetti peut mettre en danger le développement complet d’un logiciel. Alors, même le refactoring ne peut plus résoudre le problème.
Moins graves, on distingue aussi les codes smells et la pourriture du logiciel. Avec l’âge, un code peut commencer à « sentir », au sens figuré, à cause de lignes sales. Les lignes difficiles à comprendre empirent avec l’intervention d’autres programmeurs ou l’ajout de compléments. Si, dès l’apparition des premiers codes smells, on n’entreprend aucun réusinage du code, celui-ci se dégrade visiblement et perd sa fonctionnalité : il pourrit (de l’anglais « code rot »).