Si vous optez pour la mutabilité, vous constaterez qu'à chaque fois que vous devez appeler une méthode dont vous ne voulez pas que l'objet change, ou que vous devez renvoyer un objet qui fait partie de l'état interne, vous devez faire une copie défensive.
Si vous examinez vraiment les programmes qui utilisent des objets muables, vous constaterez qu'ils sont sujets à des "attaques" par modification :
- les objets passés aux constructeurs
- objets passés aux méthodes
- les objets renvoyés par les méthodes.
Le problème ne se pose pas très souvent car la plupart des programmes ne modifient pas les données (elles sont en réalité immuables puisqu'elles ne changent jamais).
Je fais personnellement tout ce que je peux finaliser. J'ai probablement 90%-95% de toutes les variables (paramètres, locales, d'instance, statiques, exceptions, etc...) marquées comme finales. Dans certains cas, elles doivent être mutables, mais dans la grande majorité des cas, elles ne le sont pas.
Je pense que cela peut dépendre de votre objectif. Si vous écrivez des bibliothèques destinées à être utilisées par des tiers, vous y pensez beaucoup plus que si vous écrivez une application que seul vous (ou votre équipe) maintiendrez.
Je trouve que l'on peut écrire des applications à grande échelle en utilisant des objets immuables pour la majorité du système sans trop de difficultés.