This is key advise. It makes the difference between a person who enjoys the art of coding and a professional who get paid for work. Basically you have to first proof why the invest of rewriting brings any financial benefit. Till then, be professional and maintain it.
I mean, you are offering good advice for a person that wants to fit in as his highest priority, no doubt about that. But there are people (like me) who don't enjoy working deep down in complicated shitty code to the degree that I don't even want to be a programmer in such environments.
There are ways to mitigate this. Join companies that care about clean code and micro services. Work in the cloud. Avoid enterprise. Those advices can be hugely important for someone who just hates those kind of gigs where you feel like you don't want to be there even.
Any codebase that sees real usage will accumulate cruft, odd behavior and legacy code over time. Dealing with that and assessing what’s worth refactoring and what’s best cut or even just left as it is to reach a business goal is the skill that differentiates a seasoned engineer from a code monkey. That shitty legacy code is often what brings in the money to sustain the company, otherwise it would have been turned off long ago.
Microservices don’t help much in that regard: each micro service can look squeaky clean from a code perspective and the whole system can still behave in shitty, unpredictable ways. (Been there, seen that)
It’s also not about fitting in: taking on a shitty codebase and transforming it into something better is an outstanding skill and requires constant communication with all stakeholders, especially when you want to cut legacy stuff. It’s certainly not something for people that prefer a quiet corner.
How is this even related? Worst code I've seen was in financial sector, but the project is so huge that is no chance of upgrading it without complete rewrite, 65% of code when I left it was still in Java5 with no option to upgrade to 7 any time soon, it's just too big, so we can understand why it's shit. Second worst code was in a startup, micro-service oriented code, k8s, dockers, javaEE, angularJS and angularIO + TypeScript. There was literally shit, HTML injection in chat-box, >200 JSON endpoints with something that mimics REST (it was closer to CURD than to REST), SQL injection using JSON objects was possible, deployment of new version of a microservice usually took 4-5hours, only if any of model classes haven't been changed. Now I work on medical software, the only split we have is frontend has own repo, backend has own repo, two monoliths. Best code I've ever seen, perfect organisation, good class and field names, easy navigation. I see completely no relation between code quality and microservices/monoliths, what I see it that sane people write good code.
Sure, enterprise is slower with moving with technologies, but that's because they're bigger and decision on upgrading Tomcat to the latest version might cost thousands monthly if there is a single performance regression. It doesn't mean that code is shit because they still use jQuery instead ReactJS.
>Work in the cloud
How is that supposed to help? Moderns devs already have to know JSON, XML, XSD, 2 IDEs, 10 testing framework, at least 2 frontend frameworks and languages, at least 2 backend frameworks and languages, so here, have this k8s YAML configuration and this docker-compose and Dockerfile so you can... avoid shitty code? Also, have this microservice oriented stack, learn how to do distributed logging, autoscaling, self-healing architecture, deploy chaos monkeys in your cluster.
I agree that work should produce happiness. And I agree there are places where the work is not everyone's fit (e.g. bureaucratic customizations). But being not able to cope with bad code is a no go in my opinion.
That said, any codebase that has seen a few years of maintenance and further development is going to look complicated, especially if you're too young and inexperienced to recognize that each of the annoying edge cases was put there to fix real production issues. Rewriting sounds like a good fix, but it will take a very long time and in the best case you'll end up with a newer codebase that looks just as complicated to a person just entering the business as the one you were attempting to replace.
Also I want to add that allocating time for a refactoring or fixing legacy code is hard to justify most of the time. Instead I try to follow the "boy scout rule":
On every bug fix or new feature you work on "Leave Things BETTER than you found them". An small change like properly naming a class or a variable, or just writing a readme file explaining something will help you and your team in the future.
https://medium.com/@biratkirat/step-8-the-boy-scout-rule-rob...
I would agree with this, you need to be careful. I've seen a friend start at a new company with a horrendous code base, bring up the issues and be let go because they hurt / offended the existing developers.
SOme people are really precious about their shitty code and can't take criticism, esepcially in small companies.
So get through your probation period then you can maybe start making noises.
It's very easy to criticize, often not easy to understand the situation where the bad code was written. Maybe the hastily-written code was the thing that saved a company from bankruptcy and was written by dedicated engineers, and bringing your friend to fix it was the plan all along, and what they needed was someone to fix the code and not decry everybody as stupid.
[I'm not saying this is what actually happened to your friend. I don't know your friend :)]
A lot of people seem to think that criticism of the code is the same as criticism of the person who wrote the code. They are not the same thing. Root knows I've written plenty of crappy code over the years for very valid reasons. You are not your code, saying the code sucks doesn't mean I think you suck.
Some people take _any_ criticism of their code personally regardless of how constructive you are being.
I have had a person completely blow up at me for simply asking (literally a question - a valid question) "why did you choose to use a BindingList instead of a List?"
Maybe it was how I phrased it? People are tough to get sometimes.
#notacoder
This is not applicable to every piece of code and roi should always be kept in mind but I'm my experience it is almost always the case
It applies to a lot of business areas. If you want to introduce new processes or fix any problems, you need to justify why you want to do that, and "This isn't very pretty" isn't generally considered a good enough reason. If something works, nobody ever got into trouble for leaving it alone.
If it's a smaller company (op mentioned 50-100 people) they might not even know what RoI is, and/or might not care about it.
I'm not sure if I agree. As a programmer I feel my primary responsibility is towards the code, not the company, not my colleagues feelings, not the customer. There are other roles who speak for them (sales, product owner, managers, etc.), I speak for the code.
When you get into the office in the morning, you hang both your coat and your ego on the coat rack, you can pick them back up when you leave. If someone can improve the code by tossing away 3 years of my work, then by all means. Doesn't matter if the person who suggested it is a senior with 20 years experience or the fresh out of college guy/girl who started just last week. You judge the idea on it's own merits, not by who suggested it.
I really don't get the tendency of allistic people to involve emotions in parts of their life where it's not helpful at all.
If someone approaches things politely and professionally then no one should have a problem with constructive suggestions for improvement. But people sometimes approach things in a combative or disrespectful manner and that's when you run into problems.
But how do you objectively measure "improvement of the code"?
Maybe it's something fairly obvious like better performance, less bugs, etc, but a lot of times it's very hard to tell if there was actually an improvement or just a different way of doing the same thing, except at the added cost of re-implementing those 3 years of work.
And for the record, I agree with you in that you (we) should leave your ego at the door, and if some young whippersnapper can do better than you, then you should be able to leverage that and increase the productivity/performance of the team/company.
However I've seen it happen many times where someone thinks they will improve the code but in reality (like others have said) they don't have the correct context and forget about a lot of stuff that their "improvement" should take into account but doesn't... and then once they do the "aha!" moment kicks in and they realize why it wasn't as easy to improve as they first thought.
>I really don't get the tendency of allistic people to involve emotions in parts of their life where it's not helpful at all.
I complete agree
You're absolutely right: if someone has a good idea for improvement, it should be adopted regardless of who they are.
The difficulty is that the suggestion of a total rewrite is not-infrequently prompted by a mostly-emotional reaction. It may not be taking all the important objective factors into account, so you have to be careful to assess whether it truly is a good idea.
The directors and the team leader appreciate the honesty and my initiative to make the codebase healthier.
Like Ray Dalio says, 'don't tolerate shit'.
P.D: I rewrote a huge section of the application on Vue2 with SFC's. The other three developers who wrote backend mostly, tried to do the FrontEnd, but made a complete mess.
If it's really a rewrite job, you'll end up with a lot of entries in there of varying size and complexity. You can start moving those issues across to whatever issue tracker your boss does keep an eye on as you get to them.
That way, you're not just walking in, announcing that the entire lot is garbage, and wasting time rewriting it all (which is what the business will think you're doing if the current implementation is at least vaguely functional), but you're gaining familiarity with the code and compiling a decent sized todo list that you can present at the appropriate time, as well as a list of fairly quick wins that you can get done when you have some downtime.
In my mind, unit tests is not what you want to start with with a messy legacy codebase. It takes a huge amount of effort testing lots of already working code. Add unit tests for any new code, but try and implement tests for the entire system, functional/integration tests are also easier to argue for in terms for direct benefit for the customer. Unit tests are more for the developer and is harder to argue for.
Adding tests makes it easier to confidently refactor the code later on.
Start with areas that are the most valuable to the business. Not only does this more easily show the (business) value of testing, but it helps keep you from introducing a very visible and very bad looking regression. Anything dealing with money (especially billing) is probably a good indicator. Be warned, here be dragons.
That being said, don't verify your testing setup with business critical tests. Verify your setup (to yourself and other devs) with the quickest thing you can accomplish. The business critical ones are your (team's) short term goal.
Pick out the X most important logic paths (e.g. customer checkout or some subsection of that). Work on regression testing that over the next few months.
Make sure your tests are both automated and actually get run. The latter is more important than the former.
Ideally, your tests will prevent a nasty bug from going in and will immediately prove the business value of your testing efforts. This will establish the trust you need to continue testing and refactoring.
The first step is to stop the bleeding so begin adding unit tests for any new code you write and be sure to factor this effort in with your sprint estimations.
In parallel work top down with high level integration tests written against feature flows. E.g., As a user when I select this then I expect this. This doesn't mean you need to actually use BDD gherkin library for your test runner but at least frame the context of these in that regard since you don't care about the minute details of the underlying code, just the experience of the user story.
And lastly, don't just write tests to write tests, try to understand what is important to cover against because there is nothing worse than maintaining barely useful tests wired up to legacy data fixtures.
Without that, IMO trying to internalize large amounts of badly written code can negatively affect your brain's ability to come up with good, well written code. All those bad ideas and patterns become the first things that pop into your mind when you try and solve problems.
“When you stare into the void, the void stares back into you” sort of thing...
I don't usually change the details of nodes that I already worked on, but rather write what has changed in a new node with the same name but under a later date node. I find that it becomes a mess if I try and keep every node updated to what I currently think about it, because too much information builds up to efficiently do so. Also, a lot of what I write only make sense in the context of what I wrote on other subjects during the same time period, so if I change one, I end up having to rewrite more and more, which eventually becomes a big mess.
The main benefit is that I can go through my notes quickly, skipping minutia of topics I'm not interested in simply by not reading the details of a node. I used to use a text file, and that was a very big problem, because not only would the amount of text that I'd have to go through became daunting. Also, I sometimes found it hard to interpret what I wrote, which means I wouldn't know if it applied to the problem I was working on or not.
However, in contrast to the above, I do try and make a definitive structure if it's a small topic or a quick idea for a new project or something simple like vacation plans.
BTW, it also works very well for taking notes for a class or self-study.
Edit: "you" = OP
Plus, to my mind, there's no better way to start understanding a new codebase than to start with tests, either writing them or reading the existing suite.
Even if I didnt do anything, the code keeps breaking!
My advice is don't complain and don't attempt any significant rewrites for the first 6 months or so. Your job at first is simply to understand the code and demonstrate that you are able make improvements to it without breaking everything. Doing so will win you the trust and respect of your teammates, whereas if you come right out of the gate trying to rewrite everything there is a very good chance you will make yourself look like an ass by spending a lot of time and energy introducing bugs into a previously-stable area of the code. Once you have a decent understanding of how and why the code is the way it is, and the trust of your teammates, then you can invest effort into fixing the highest-priority issues with the code.
Being able to read and work effectively in legacy code is an essential skill for any software engineer. For now you should just try to focus on fixing bugs and implementing new features, and take pleasure in the fact that you are improving the project and developing a handful of hard and soft professional skills.
That being said - there should be a limit to how much bullshit you put up with. If after six months to a year you still find that you hate the job, and a better opportunity comes along, then go ahead and take it.