50

A long time ago we added a feature where our users could "Accept" an image after it was added to a workflow queue. Turns out, we used the wrong term, and users actually "Approve" the image.

Changing Accept to Approve on our interface is easy, just replace one word. But we programmed all layers with the word "accept", from the CSS class name to the database values.

  • The CSS class that turns the button green: ".accepted";
  • The model method that verifies and binds the class attribute on the DOM node: "isAccepted";
  • JavaScript status attribute: Array with "unreviewed", "accepted" and "published";
  • Mysql status column: ENUM with "unreviewed", "accepted" and "published";
  • Test names;

It's trivial (specially when you have tests) to replace most occurrences of accept to approve. A little bit harder is to migrate the data, specially since it needs to be synchronized with deployment.

This specific case is simple, but I've faced similar, yet more complex cases, during my career. When a file is also renamed and deployment happens on dozens of servers, or when proxy caching, memcached and mysql are involved.

Leaving "accepted" on every other layer except the interface is a bad idea, since new programmers joining the team might not learn the historical reasons it led to this decision, and while accept -> approve are close words in terms of meaning, if it was renamed to "queued for managerial next status meeting", it certainly wouldn't make any sense. And it feels if we compromise here and there, in a few iterations the user interface concepts will have no bearings to the system internals, and I certainly do not want to work on a system where half of the output has no connection to its innards.

So, do you always rename everything when needed? If this happened to you, and you decided that the trade-off was not worth, did it come back to bite you? Is code comment or developer documentation enough to avoid this issue?

4
  • 6
    Like many things in programming, it is a trade-off. You make a decision based on the relative advantages and disadvantages to either rename, or leave it the way it is. Dec 5, 2013 at 19:01
  • 1
    I would use this as an opportunity to improve your tooling. Start from the premise that this should be easy, work out why it isn't, and make sure it will be easier next time it happens. For example automated deployments will make any problems around synchronizing the data and code in production much simpler. Dec 11, 2013 at 10:12
  • I would only have to think about migrating data in db. If it's 1000 records, no doubt. Migrate it! If it's 1000000 than maybe I would think. But still think that 1 mil simple updates would be very quick. All other things you mentioned is rename for me. Dec 14, 2013 at 9:43
  • The data shouldn't need to be migrated for this, it should be using the ID (or index for enums?) from MySQL, not the text...
    – Izkata
    Mar 30, 2014 at 0:26

5 Answers 5

32

For me, it is definitely best to change everything related to the item in question.

It is a form of code degradation, and while 1 item not being changed might not be a big deal, it sets the tone for the code base.

It could also lead to confusion in the future and make it harder for new devs to understand the code base/domain.

1
  • 8
    +1. The only thing I would add (and have added in another answer) is the term "technical debt." You are right in saying this is code degradation. The cost of this degradation, however, is not a 1-off. Instead, it will make working with the code more and more difficult over time.
    – MetaFight
    Dec 5, 2013 at 19:44
14

From the question content and tags I'll assumer you're using ubiquitous language.

In my experience UL is great but, as you mentioned, can lead to additional maintenance tasks as the language evolves. This, in itself, isn't a bad thing. Sure, it's inconvenient, but it's also expected.

What I've typically done (and seen done) is either:

  • 1-shot upfront refactoring: Refactor all layers of the application to adopt the updated language; or
  • log technical debt: You can change user-facing code right away, and then log technical debt tasks to bring the rest of the application layers in line with the updated language. This typically results in a handful of boring (but manageable) tasks. (Perfect for 5pm!)

I think the key thing here is that what you're describing is technical debt and should be recognized as such.

I've had managers who've argued that we shouldn't be wasting time on such trivial tasks that don't add any visible functionality. This is when the debt analogy really comes in handy. It boils down to this:

The team chose to do DDD with Ubiquitous Language. Straying from this approach by leaving the code in an inconsistent state adds confusion and removes many of the benefits that DDD and UL provide. In manager terms, it adds cost to the project. The code becomes more difficult (expensive) to manage, and more confusing for new developers (expensive).

6

You may want to look into Localization (l10n) options. While it may not seem as drastic as going from English to Spanish, you're dealing with a different term for the same concept. If this seems to happen commonly, then using l10n can allow you to quickly change what is displayed in the user interface while not having to change the term used in code.

With that in place, just use the terms in your code that are the most widely understood. Choose names from the domain as developers know it and might expect it.

9
  • 2
    I think the OP is talking about a different problem. The hurdles he's describing seem to stem from using a Ubiquitous Language ( c2.com/cgi/wiki?UbiquitousLanguage ). When using UL you actually do want your code to use the same language (nouns, verbs) as the UI.
    – MetaFight
    Dec 5, 2013 at 19:42
  • 3
    @MetaFight It depends on philosophy really. Suppose the idea of Code as Communication, you're writing something that tells the system and other developers what you want the system to do. If the client is not going to use the code, then I'm proposing writing the code using language that is most intuitive to the developers, and then translate the UI for the users. There are two different audiences. If your client spoke Spanish, and you English, would your variables be written in Spanish or English? So I propose l10n as a way to serve both audiences.
    – CLo
    Dec 5, 2013 at 21:30
  • 2
    Another case for l10n is when marketing decides to invent their own terms. Dec 6, 2013 at 7:04
  • @BartvanIngenSchenau hrm, that's something I've never had to deal with myself, but is clearly a possibility. In this case I can see how l10n could be useful when the language the team and Domain Experts use differs from the Marketable language. Very interesting.
    – MetaFight
    Dec 6, 2013 at 9:44
  • I'd love to know why marketing isn't involved in the beginning, honestly. I'd also like to know what environment you work in where the domain experts aren't directly invoked with customers. Presumably your customers should drive the nomenclature and further your marketing department should be using terms that your customers will recognize as being meaningful. Dec 9, 2013 at 0:37
6

As you appropriately depict this, tracking end-user nomenclature changes in every part of the source is quite an investment. It is however definitely worth it, especially for a long living product developed by a complete infrastructure (with hotline, testers, etc.)

Tracking end-user nomenclature in source is an investment is because there are so many component types where it appears and there is no magic wand working simultaneously on all these components. Maybe developing such a magic wand, component after component, is an interesting investment that you can dilute over the lifetime of the project.

I worked on a 30-year old codebase where the drift between end-user nomenclature and internal nomenclature grew especially large. Here are a few drawbacks of this situation, which all add to the overhead of everybody's work:

  1. In the absence of an adequate policy, new development tends to use the current end-user nomenclature. Thus, the same concept may have two or more names in different components. Since the components interact together, this results in several synonymous names existing simulatenously in some local parts of the code.

  2. When the hotline/help desk is called, they write down a user story using end-user nomenclature. The developer in charge of fixing the problem must translate the end-user nomenclature to match the source nomenclature. Of course it is not archived, and of course it is a mess. (See 1.)

  3. When the programmer debugs the code, she wants to set breakpoints in relevant functions. It is hard to find the appropriate functions if the end-user nomenclature and the source nomenclature do not agree. It might even be hard or impossible to be confident that a listing of the relevant functions is even complete. (See 1.)

  4. In absence of an adequate policy, maintainance of source using an obsolete nomenclature will from time to time put this obsolete nomenclature in front of the users again. This produces poor impression and causes overhead.

I already tracked down two days long the very place where some data is read off the database and injected in some component of this codebase. Because whether I nor anybody at the company I worked was able to figure a name leading to this place I finally dismissed and decided to find another solution to that problem.

While costing more than[1] two days of maintenance without yielding anything (no knowledge, no fix, nothing) is probably as bad as it can get, discrepancies between user-nomenclature and source nomemclature add overhead to many routine task in the maintainance of a software.

It is important to remark that the overhead cost grows with the company producing the software, in a large organisation, a problem report will not arrive on your desk before it has been considered by several colleagues and the fix might be subject to test.

[1] Because of more than one developer being involved.

0

I don't always rename code and data because some packages are shared between customers. They are basically using the same thing but call it differently. Examples, in a CMS, one client calls their customer "Customer" and another uses "Client". So we replaced Customer with Client on the surface for one client, but CMS will always be a Customer Management System.

Another example is User management with terms like permissions vs access control list, admin vs manager, etc. It can be confusing to new comers but for core components like those, there are usually core developers who make sure that those components work for all clients and also easy to implements by other developers (e.g. by creating configurable labels).

It might help to think that if you do make this change, hopefully you won't need to do it again if the same piece is used by other customer, basically turning it into a product.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.