Written By: Steve Zagieboylo, Senior Architect at Calavista
This is the third part in the series, “Technical Debt Patterns.”
This problem refers to the developers speaking a different language about the problem domain than anyone else, including the users. It is a lack of what Eric Evans refers to as “Ubiquitous Language,” the term Eric Evans uses in his book Domain Driven Design. He explains (correctly) that the developers should derive their entity names from the subject matter experts (SMEs), so that they are using the same language when they speak to them. This vastly simplifies the conversations with the SMEs and other users, with marketing, with documentation, with your own user interface!
Sadly, in my 35+ years writing software, I have never once been on a project where these problems didn’t arise. Names change, specs change, marketing comes down with a new dictum, there’s always something. What we called a Cube yesterday is now called a box; Filter is now Selector, and so on. So now that it is there, what are you going to do about it?
Step 1: Identify the terms that have multiple names.
Is it just one major object, or is it dozens of little objects strewn throughout? If you haven’t done so already, make a dictionary of all the domain entities, including both (or all!) their names in developer-speak, marketing-speak, and SME-speak. The beauty of this step is that it is going to be used no matter how you end up deciding to tackle the problem. Put your glossary somewhere that everyone knows where to find it, where you point new developers as one of the first things they see. You should be using, for developer documentation, some sort of wiki that ties well into your issue tracking system. Put the glossary front and center, and then link to it frequently.
Step 2: Identify the scope of the problem.
Usually the problem is more than just the class names that refer to these dual-named entities. There are argument names, member names, and local names that are just a lowercase version of the entity name; there are usually multiple occurrences of each named entity, with data transfer objects (DTOs), service classes, unit test classes, and more; there are database tables — changing those names means a migration; and there may be a public API that would be a huge pain to change.
If you want to be able to follow file history, then good cooperation from your source control system is a must.
Another consideration is your source control system and its ability to track filename changes which is required in most languages if the class name changes. If you want to be able to follow file history, then good cooperation from your source control system is a must.
The last element of scope is the most important: Is your product one that you sell copies of the software to customers or one where the only commercial version is a single instance that you host and sell access to? In the former case, you probably maintain different versions, with point and sub-point releases. If your new development is on version 7.x, but you still support 6.3.x and 5.8.x, then your transition period where developers will have to develop in both languages becomes a huge nightmare. If that’s the case, I would suggest that just good documentation and socialization of the problem is going to be good enough, because actually fixing it is impossible — those old names will still be in your older versions of the code.
Step 3: Change Ahead!
Plan when it is going to happen, possibly just after a major release when everyone is going to be taking a breath.
If you’ve decided that you do want to fix the problem, the biggest challenge will be timing and branches. Plan when it is going to happen, possibly just after a major release when everyone is going to be taking a breath. Make sure the developers all have their code checked in and merged to the main branch, because these changes are sure to cause merge conflicts with everything. Use the refactoring tools in the IDE just to change the names of all the classes, and don’t bother with the secondary uses, the member names, argument names, and local variables, unless the refactoring tools will do this automatically. Now get it all checked in and run your unit tests. If this goes smoothly, congratulate yourself because you’ve done better than I ever have.
The next step, if you’re going to do it, is to take the database tables. Because this needs a migration it will take longer. If you are changing column names within the tables, it will take longer, still. Fortunately, this should be reasonably isolated, so this can be drawn out and you can let the developers start making branches again. Honestly, in the times I have attempted to move to the Ubiquitous Language, I’ve never changed the database table names. I just documented in the few classes that touch the database directly, and kept my glossary up to date.
Of all the Technical Debt Patterns, this is the one that I would most likely recommend that you don’t try to fix it, just mitigate it with good documentation. First, it is a minor inconvenience but not really crippling unless you really have a lot of churn on your development staff. It is more of a pain and an embarrassment when you are introducing new developers to the team, and once they are used to it, it doesn’t cost that much. The other consideration is how much of a moving target it is that you are aiming at. If the product is a new, world-changing paradigm (and what isn’t?) then you can count on marketing changing all the names again in another quarter. They might even change back to what you used to have. So, unless you have a pretty stable product, I would recommend just to live with it.