I am currently working with a company which has produced a lot of useful, but old code. Many of my peers and software developers have spent a lot of time building this library and use it extensively. Importantly, the library was useful and necessary back when C++ was apparently not as well developed, but is very outdated and C-styled nowadays. I am having a lot of difficulty progressing with writing software that requires so much maintenance.

For example, my peers prefer raw arrays to vectors, and their own string class to standard strings. My peers know this as well, but since so much of the codebase is built with our own implementations of lists and containers, it is economically not possible to refactor our code without writing it from scratch.

What steps can I take to integrate myself better into using their code and making my code adaptable with legacy code, while still practicing modern coding standards?

  • 8
    In these types of situations, I recommend you listen before you judge. Why do your colleagues prefer their own string class to standard strings for instance? Why was was this decided or was it a formal decision? What are the pros and cons to switching to standard strings? How long would it take to switch over? etc. – jcmack Jan 2 at 23:02
  • 6
    Whatever you do don't refactor old code unless you fully understand it AND are tasked to refactor it. – JonSG Jan 2 at 23:04
  • 1
    @jcmack From what I am aware, situations regarding custom classes for STL counterparts were made because they did not exist, or because they were too slow at the time (we built real-time systems). We are a small company so moving over custom classes are simply not realistic; I would guess over a year to refactor everything. I have been explicitly told that most of our developers dislike our custom string class, but they persist due to compatibility issues and deadlines. My difficulty is balancing legacy code and modern cpp which is subjectively more readable and maintainable. – Michael Choi Jan 2 at 23:09
  • 1
    @JonSG I am not suggesting to refactor old code. I'd like to find a way to find a balance between working more effectively with readable code, and maintaining legacy features. – Michael Choi Jan 2 at 23:11
  • 1
    @MichaelChoi I totally understand. It's pretty important to work within the existing management structure at your company to bring up an initiative like this one. As a manager or senior leadership, I would definitely want to know timelines, numbers of people needed, pros vs cons and migration/deployment plan. With an effort as big as a year, I would definitely recommend an incremental strategy if possible. – jcmack Jan 3 at 0:14

Legacy code is part of software development life cycle. We work in the fast-changing environment. This beautiful class you're writing today could be considered ugly and obsolete in just a few years. So my first advice would be: don't make judgments if you don't know for sure why exactly it was decided back then to go this particular way. Maybe, not all of the options were known, and "the worse one" has been chosen not intentionally. And now, as you mentioned, everybody knows better practices, but they prefer to stick to that style for consistency reasons. And being pragmatic, it makes sense to keep everything in the same manner, doesn't it?

With that said, I would recommend being vocal about your improvements ideas. Perhaps, nobody will ever allow to re-write the whole thing. But coding standards are the subject for continuous improvements, and a healthy team understands that. How about making a presentation on why vectors are better than arrays? Or starting a discussion in a team chat/email about the appropriateness of custom implementations for standard objects? Of course, it would be nice to share a couple of links, let's say, to blog posts from big names in the industry, to strengthen your position. And when you'll have any kind of consensus after these discussions, be proactive and create a poll about acceptance of this idea as a standard from now on. Even if it won't be accepted, you'll learn something that is unknown to you at the moment.

But if it will be, you'll see how much you can do even if the codebase is old and big and it is seemingly impossible to fix all. Start with baby steps: have this rule working only for a new code, even if to implement a new feature you need to touch old parts of the system where many methods are still "ugly". Next, apply the boy scout rule: if you see "the old style" somewhere on the way, and it takes not more than an hour to fix it, - rewrite. Then, if applicable, an automated check could help to detect all of the places that need attention and estimate the real effort to absolutely get rid of this (it could be surprisingly small, by the way). And if you add this check to a pipeline, you'll force everybody to fix that stuff even if their task was not related to that particular method with an "old style". With all this one day it will disappear, I promise.

And one more situation to show that changes are more possible than you might think. In the business world, we need to speak in business terms. Refactoring for the sake of refactoring itself adds zero value, but when you are able to demonstrate how this change will impact results, you'd likely to get the green light for any request. Sometimes, the maintenance of one particular part of the code is painful, while the reasonable rework effort will speed it up dramatically. I encourage you to speak up instead of struggling with it. Bring up some numbers, make rough estimations on how long the feature enhancement will take with and without refactoring. Sell this work to your tech lead/product manager/another relevant influencer as necessary, and the choice would seem obvious for them. After this success, "suddenly", you'll find yourself leading a project of making this part of codebase a place where modern coding standards come to play. Go for it! Just be sure to have tests for all the critical functions before you even start! ;)

Good luck, Michael.

  • An excellent answer (+1)! Also, be aware of the canonical book Working effectively with legacy code - it's a must read for everyone in the OP''s position. – Mawg Jan 3 at 7:55
  • @vladimino I appreciate the thought out answer. I think I'll try to put it into practice. I am actually just starting out in my first year professionally so I am definitely a rookie, and definitely don't understand the applications of our company's custom classes completely. That being said from the experience I do have, I can tell which classes are showing age and I think I'll take your advice on very small incremental changes. – Michael Choi Jan 3 at 16:13

C++ is somewhat of a unusual language. The libraries tend to not check for errors or boundaries. Many assume certain conditions to work and it's up to the developer to check those conditions before passing into the function. A good example is the strlen function which can cause a buffer overflow since it assumes a nul terminator.

This causes unexpected behavior. I seen cases where a buffer overflow caused a random file to get deleted on the machine. It happens seemingly random and at strange times and conditions never consistent. Debugging became near impossible since it looks like it worked. It was only after an accident that the error was found and the conditions never occur again.

Then there is the whole garbage collection, dangling pointers, etc. Lots of dangerous things exist in C++. Your library may check those conditions or keep track of a built in auto pointer/garbage collection.

Point is your coworker may have wrote libraries that check for conditions and boundaries. I would first ask directly why not use the library function X as oppose to the in house methods. See what they say.

  • Yes, C++ was always dangerous, as it assumed programmers knew what they were doing. C even more so. – Richard U Jan 3 at 18:54

In addition to vladimino's excellent answer, you could suggest to your boss to make some evaluations (maybe half a day per week).

Metrices could be:

  • performance (time) with own implementation and with STL containers for some examples
  • Time spent to fix bugs related to arrays etc, e.g. out of bounds errors (often hard to find)

So you could build a case with numbers if a refactoring would add business value. Or maybe not.

Another idea would be to extend the own containers to make them work with STL algorithms, i.e. providing the necessary methods.

Your Answer

