5

This question comes when there are changes during development and some entity of the business changes its name or its purpose. When it comes the time to develop, it can get very confusing during meetings, development, or any process that you mention that entity that has just changed.

Suppose we're in a business of plastic cups, so we create everything over that name. But for some reason, there are not plastic cups anymore, there are glasses, they work different from plastic cups, but not so different. In code, there should be a refactor of names? Or is it better to create a new object? Or better not to do a thing?

Does this code should change like this? :

public class mainClass(){
    private PlasticCup fullCup;

    public PlasticCup createNewCup(){
        fullCup = new PlasticCup();

        return fullCup;
    }
}

To:

public class mainClass(){
    private Glass fullGlass;

    public Glass createNewGlass(){
        fullGlass = new Glass();

        return fullGlass;
    }
}
4
  • 1
    hmm.. I think also a consideration to potentially doing a DDD code refactoring would be in regards to data schema changing efforts.. – Brett Caswell Sep 23 '20 at 1:03
  • But what if the code was not made under DDD? I've thought about changing the core Classes and expect the IDE to throw a hell of errors, but it's not only the core Classes, but the names of the variables. I think that having things like Blue red; are mala praxis. – user375277 Sep 23 '20 at 1:19
  • 1
    well this kind of goes into a semantics conversation defining\depicting what facets domain driven design, I would think you probably don't have business types and variables reflecting products, services or company name if you weren't DDD. but I was really only raising consideration and regards to db schema efforts in this same vein. – Brett Caswell Sep 23 '20 at 1:29
  • 1
    I don't have an answer for this question, as I haven't experienced such a scenario or work; but I think a good scenario could be related experiences with azure devops rebranding. – Brett Caswell Sep 23 '20 at 1:36
7

This depends heavily on the circumstances, and on factors like

  • How many people work with that code, actually come in contact with such internal names, and get potentially confused when the name is changed, or might get confused in the future when the name is not changed?

  • How different are the meanings of the old name and the new one really?

  • How much work will the actual renaming really cause. This depends on further things like how much code exists which relies on that name, how powerful are the available refactoring tools, and necessary changes to documentation, extra testing and debugging efforts.

  • Are there persisted entities with the old name which must correspond to the class name in code because of the used persistence technology? Will you have to support them for backwards compatibility? How costly is a conversion of those persisted entities?

  • Is it really just a name change, or also behavioural change, where the new behaviour does not really fit any more to the old name?

  • What is the expected life time of the code which contains this name? If it is expected to live for decades, a renaming is probably more benefitial than for code which is only expected to be used until next quarter.

  • Is there a more general name, which may cover the meaning of the old as well as the meaning of the new entity in a conclusive way?

In the end, it is a trade-off. One has to make a cost-benefit analysis, taking all those bullet points into account and then make a decision.

2
  • I respectfully disagree with the first bullet point that the size of the codebase (or at least how much code contains the to-be-refactored name) influences whether the refactoring is warranted. It can definitely influence whether you do it now or put it on the backlog, but it doesn't change whether it should be done. (Other than that, I agree, so +1) – Flater Sep 23 '20 at 9:30
  • 1
    @Flater: I edited my answer a little bit. I guess you will agree that size of relying codebase can influence the costs of a renaming, so I mention it there to make this more clearer. – Doc Brown Sep 23 '20 at 11:11
3

This answer is touching on things mentioned in other answers, but I wanted to explain it in a way I find easier to understand.


There is a huge difference between data and logic. Data is much more easily changeable than logic. Almost by definition, data is something that can change without requiring redevelopment, whereas changes to logic always need some kind of development effort.

However, when you have data alongside your logic, you have to integrate your logic to use that data. Developing logic that handles data takes a non-zero amount of effort. If the data in question doesn't change, then there's no real point to abstracting it as data. In such a case, we hardcode the information in the logic. It's the least-effort approach.

And don't get me wrong, that's not inherently bad to do. Some thing simply don't need to be abstracted. If we abstracted literally everything that could be abstracted, we'd have countless more layers of abstractions in any codebase, without really adding value to that codebase.
There should only be as many abstractions as you need; not as many as you can implement.

Take the example of a bible salesman. They only sell bibles, no other books, and therefore the "bible" concept can be hardcoded in this bible salesman's codebase:

public void SellBibleTo(Customer c) { ... }

This is perfectly fine as long as they only sell bibles.

But just like in your situation, that rigidity has ceased to exist when this salesman begins selling other books as well. At this point, the code needs to be re-evaluated to account for a much more abstract approach: the ability to sell any kind of book.

It is at this point that the hardcoded needs to disappear, and we need to introduce actual data (including handling) that allows for different values to be used, in this case books.

The codebase will end up with another layer of abstraction:

public class Book { ... }

public void SellTo(Customer c, Book b) { ... }

This is more than just a rename. That's the most important thing to take away from this.

Now, your code can no longer assume that it innately knows which book is being sold, and thus the choice of book becomes an input parameter to your book-handling (previously bible-handling) logic.


Moving back to your example, the issue with your approach is that you are merely attempting to rename your logic rather than expand the logic itself.

If your client has decided to also handle glasses instead of just cups, it becomes clear to see that products can change. It's highly likely that your client is going to handle a third, fourth, fifth, ... kind of product down the line.

When things need to be able to change, they are data that can no longer be hardcoded. Therefore, just like how we needed to expand our example logic to handle any kind of book, now we need to rewrite the logic to handle any kind of product. I'm calling it a "product" for lack of a better name, I don't know your company's market focus.

I was going to refactor your code example but it's not a particularly meaningful one to rewrite since you're only using a hardcoded parameterless constructor in a factory whose name doesn't describe its purpose.

So I'm going to create my own example here. If your old code was this:

public void ShipCupToCustomer(Customer customer)
{
    var cup = new Cup();

    washer.Rinse(cup);
    
    var box = packer.Package(cup);
    
    labeler.Label(box, customer.Address);

    shipper.Ship(box);
}

Then your new code would be something along the lines of:

public abstract class Product { }

public class Cup : Product { }

public class Glass : Product { }

public void ShipProductToCustomer(Product product, Customer customer)
{
    washer.Rinse(product);
    
    var box = packer.Package(product);
    
    labeler.Label(box, customer.Address);

    shipper.Ship(box);
}

It's not a huge change, but it is an extra level of abstraction.

Note that this will also cause you to have to change the washer and packer objects' interfaces to account for all Product types, but this example is meant to be short and simple.


Being able to spot this trend early is going to enable you to be prepared when it does eventually happen. It's okay that you didn't spot it during the first version, but now that you have direct experience with this kind of thing happening, you should respond to it accordingly.

1
  • Your answer is very interesting, it gives me a new approach that I think it's completely fair. The bad news that this is not the case... Being specific, I have 2 cases: 1) A company that just changed the name of DB class because business changes. It's only name, functionality still growing the same way as it would be with other name. 2) An early-staged project that requirements are constantly changing, so something that was the main entity, it is not anymore, and it has a new purpose, adding a new level up from it. – user375277 Sep 23 '20 at 17:16
1

I think you should not avoid the renaming because - as you already experienced - this can lead to a lot of confusion. Your example is of course very significant so based on the real situation a simple renaming might not be enough. A glass will have different characteristics as opposed to a plastic cup.

But in case it is only the name of some business entity which is changing due to changing business terms I would invest in rename refactorings which can be very simple if you have a good IDE (option A).

If there is more to change as I would assume of the plastic cup to glass evolution I would first grab a whiteboard and find all similarities of the two entities. Then I would refactor in several steps by first trying to refactor common stuff into maybe some new value objects (if that has not happened already) or even some new entities which are common to both plastic cup and glass.

This makes it easier to do both either refactor the existing plastic cup (option B) entity which also includes renaming of the entity. Or introduce a new glass entity (option C) which will use the same common stuff. And later on you could sunset the old plastic cup entity altogether.

Option B makes sense if plastic cup and glass do not differentiate from each other that much. Option C makes more sense if they only share some stuff but still have significant logic differences which need to be added as new code anyways.

Note: I would only invest the effort (either option A, B, C) if the business has come to a well thought decision and something like this happens very rarely. In addition, the efforts for the change in the code (and potentially other depending modules) with the avoidance of communication problems and confusion betweeen development team and business people have to be weighed out against sparing the effort but changing code but being faced with confusion and inconsistencies between requirements, domain concepts and the actual implementation.

1
  • 1
    I'm between A and B, because if both entities will coexists, I'll just make an abstraction that manage them both. But there's name and functionality changes, and there is not going to be plastic cups anymore. And yeah, these scenario is rare, so the efforts is worth. – user375277 Sep 23 '20 at 17:21
1

Separate the things that change from the things that stay the same.

Suppose we're in a business of plastic cups, so we create everything over that name. But for some reason, there are not plastic cups anymore, there are glasses,

At this point it's a distinction without a difference. All you've shown is that the name should have been more abstract.

they work different from plastic cups

But here you show a need for a new class with a new name if for no better reason than to avoid destroying old tested proven plastic cup code. Even if you know you'll never make a new plastic cup again, which you don't, having the original code under the original name is less confusing as you convert to the new one.

but not so different

And here you show a need to factor out common behavior in a third class. If you feel that’s too much then just forget OOP and write some procedural if structures.

One of the signs of good code is code that’s easy to change. Do what makes it easy to change.

2
  • 1
    To be fair, OP wrote "they work different from plastic cups, but not so different". So I don't think it is crystal-clear if making a new class or renaming the old one is the more natural option. – Doc Brown Sep 23 '20 at 15:23
  • Is 50% renaming and 50% changing logic. Not a completely overhaul of logic but still different from a plastic cup. If they come to coexist together, I just create a new class, but this case plastic cups cease to exist, but great part of the code works like plastic cups. – user375277 Sep 23 '20 at 17:25
0

This is tricky. Let’s say your company has a “support” department. Everyone knows what you are talking about when you talk about “support”. So the name has entered your code base, like in a method called “sendEmailToSupport”. And now the company changes the department name to “complaints”.

You’ll have to make code changes. Like some code will now send an email to “complaints@company.com” etc. That’s needed, and it’s not refactoring.

What about that method “sendEmailToSupport”? I’d suggest refactoring it. It’s not urgent. Do it when “complaints” has some foothold in the company. Do not wait two years until nobody remembers what “support” means and why that email method has such a weird name. (Obviously “refactoring” means changing names and comments, nothing else).

0

What's the real problem?

Considering your comments, it appears that the naming change is not necessarily related to a product change:

  • If you reuse the same code and adapt it to different companies, keeping the name of the company in your code is not an option (risk of confusion in your team, risk of customer disappointments if customer gets access to code base). You'll have to change the class-names, but also some class behaviors. You might end up with two distinct code bases that will be difficult to keep in synch.
  • If you reuse the same code and adapt it to different products, you'll need to take care for specific product characteristics and behaviors. Cloning the class and adapting it will produce redundant code difficult to synch. Modifying the original code will loose your old, verified and proven code to get a new one. You might then as well end up with multiple clones of your initial product classes.
  • If you have the two cases, it's two times the problems above :-)

What name for what abstraction?

In our daily language, diffrent concepts have different names. And when different concepts share the same name, it's always ambiguity guaranteed. It's not different for your code.

  • If you have a very general Product class that is reusable for all companies and all product lines, give it a very general name. Don't give different names to the same thing. DRY.

  • If you have product-specific or company-specific characteristics and behaviors, it is worth to reengineer your code base to express in the code the generalisation of the common characteristics and behaviors on one side, and the specialization of those in the code.

A different name would then mean a different concept. ANd anew product line would always mean a new class. Of course, this is a real design effort. But it's worth it in most cases:

  • what you have developed and tested for the general Product will continue to work, whatever the product line or the company.
  • the separation of concerns will moreover help you to maintain a synchronized code base for the general parts: If you correct a bug on the general behavior, all the specialized versions will benefit from it too.
  • if further adaptations are needed, you'll benefit from an easy reuse of your code base.

Remark/edit

I've edited my answer in view of your comment. For the records, intially I pointed out that, having worked with both plastic and glass industry and reused solutions across branches, the shift from plastics to a glass production seemed to imply much more than the naming change, since these business areas use very different product characteristics, production processes, skills and machines.

I also pointed out that if the change appeared so easy from a company perspective, it was probably because production was subcontracted, which implies that many more such changes should be expected.

I then concluded that your software should reflet raw material or product line in the name of the classes only if it mattered for the feature of your software, and suggested that if the name was kept in line with the product line requirements (concepts), a new product line would require an additional name and refactoring to isolate the common part. It's basically the same approach than here, but explained from a different angle.

4
  • It was just an example to make me understand. The company doesn't work with cups at all. There are just intellectual entities that most differ one from another only by naming (a bad client with a DB born on mala praxis). – user375277 Sep 23 '20 at 17:31
  • 1
    @user375277 ok. Thanks for the info: actually my answer is based on my experience of solution reuse across companies making really different products. So it’s not at all about product, but only about company name and some company specifics? – Christophe Sep 23 '20 at 17:44
  • I have two cases and yeah, one of them is just about company specifications. As the project is not officially released yet, it has constant changes, so it's something like "No no, there're not gonna be called cups, now there're gonna be called GLASSES, how about that?" And you got more than 5k lines of code with "cups". – user375277 Sep 23 '20 at 17:56
  • @user375277 ok , I see. I've edited the answer to be more specific. – Christophe Sep 23 '20 at 20:55
-6

Naming conventions are often enforced by the legal department. This usually happens after a company acquisition. Renaming is then done as part of rebranding process (I assume this is related to trademark law).

That decision can't be reasoned about in technical terms. Please consult them, instead of asking the engineering team.

For this reason, as a software engineer, you want to avoid including brands in any names unless absolutely necessary.

From a technical standpoint, rename has a minor advantage of consistent naming down the line, but the damage outweighs the benefit.

8
  • 2
    If a business user or analyst comes to the dev team and tells them about a terminology change in business, it is usually not the job of the devs to question this decision and talk to the legal department, that is job of the forementioned people. – Doc Brown Sep 23 '20 at 6:27
  • @DocBrown that is basically what my answer implies. The point is, that is it not a technical question. I'm leaving out of scope, whose job is it to discuss it. – Basilevs Sep 23 '20 at 8:03
  • 3
    I have yet to come across one case where the names in code are enshrined in any kind of legislation. This is not a legal issue whatsoever. Nomenclature in a codebase is meaningless post-compilation and has no bearing on anyone but the developers. – Flater Sep 23 '20 at 10:01
  • I've worked on three products, which were bought out (and rebranded) from small companies by bigger enterprises. They had to rename Java packages. When queried for main motivation, the response was - "legal issues". – Basilevs Sep 23 '20 at 10:34
  • In the case of a company getting bought out, the decision to rename products, namespaces, packages, etc from the old company to the new is largely a legal / marketing move, yes. But what you call your classes, properties, methods, etc is never a consideration for the legal department. – mmathis Sep 23 '20 at 12:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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