Ask HN: Codebase at my work is a complete mess, what should I do?

406 points by anonR4nd0m ↗ HN
Recently I joined a relatively small company (50-100 employees) as a medium level software developer. For a while I was very excited about this opportunity.

After few days/weeks of getting to know the whole codebase I finally moved to a specific project I was suppose to work on and I found out the code is a complete mess. Often I find parts of code that unintentionally affects other parts of code. Some parts are just copied and left there doing nothing. Even names of classes/variables are sometimes useless and project structure is unintuitive and seemingly without rules. It's spaghetti and relatively big spaghetti (tens of thousands of LOC).

I started "repairing" the project but there're no tests to check whether my adjustments are correct.

I'm so frustrated and depressed by it. The job basically turned into something I hate - I'm just rewriting the code! The person in charge of this project was working on it alone and from the outside it all looks fine and it's working. So this makes the higher people think that it's all just fine. I really don't know what to do. Should I just go and basically say that this person did a bad job? I don't feel very comfortably doing that because (a) I'm a relatively new hire, (b) the person in charge is working there for about two years and (c) I'm much younger than she/he is both professionally and biologically.

I've already made some comments about rewriting it and the response was basically "ok".

345 comments

[ 2.1 ms ] story [ 304 ms ] thread
> Should I just go and basically say that this person did a bad job?

That's not likely to get good results; you'll want to do more prep work to ground "did a bad job" in data. That data will also be useful in making the "rewrite everything" decision, should things come to that.

Start off at the organizational level: how did this code get into production? You're not going to get anywhere arguing for code quality at a place that doesn't value it. Is the rest of the codebase like this? If it is, you may be facing a larger company-culture issue.

Making real improvements is going to be seriously difficult without automated testing, so you'll probably need to add testing incrementally. Maybe start off by reproducing a production bug in a test and then fixing it - this delivers immediate business-visible value faster than stopping the world to write tests. Whenever you make changes, wrap the affected part in some more tests. Are there manual acceptance tests? Consider automating some of them.

Finally, be prepared to bail if nothing works - some places suffer from the "Market for Lemons" problem, where good developers who join figure out it's a dumpster fire and leave behind only bad ones.

Are you working at my company?

Ok, more seriously: that’s the way existing code is about 90% of the time - it’s the reality of working in our field.

It may or may not reflect on the original developer. Maybe they were learning a new framework. Maybe they were rushed. Maybe it was originally intended as a prototype but ended up in production. Maybe the requirements have grown or changed significantly since it was implemented and the original design didn’t scale well (this is to blame for most of the awful code where I work). Maybe they’re just not very good.

If you’re going to take this to management, I would not bad-mouth the original developer. I would suggest framing the issue as the code not scaling well to the new requirements.

Then give them a few options with trade-offs. It could be that management is willing to spend the next few years playing but whack-a-mole to avoid an extra couple weeks on the project to put it under test and refactor a bit. It could be they think the fix up is worthwhile now if it’ll save them a month’s worth of development time in the next few years, but not if it’ll only save a couple days. It could be that they intend to rewrite the entire area of the product in 6 months and only want to invest the minimum effort in changes until then.

>It may or may not reflect on the original developer. Maybe they were learning a new framework. Maybe they were rushed. Maybe it was originally intended as a prototype but ended up in production. Maybe the requirements have grown or changed significantly since it was implemented and the original design didn’t scale well

Well said. There are many possible causes behind a poor codebase, and it's rarely useful (and almost never persuasive) to go into finger-pointing mode. The issue for the OP is: from the business's perspective, is the poor code a problem? If it's not, can they live with continuing to work on this code in this job? And if it is: what's the next step, and what can they contribute to making it happen?

I think it's quite rare for the prototype to not end up in production. This is even true of the Trans-Siberian Railway [which meant people died].
If you’re going to take this to management, I would not bad-mouth the original developer.

This. If there are deficiencies in the code base, focus on those, their effects, and the gains from fixing them. Blaming people is rarely a good idea, for many reasons.

If the original dev worked on the code base for a long time, they're probably already aware of them. God knows I'm all too aware of the deficiencies in code I wrote years ago, but that's frequently how things look after years of updates and feature creep. Everyone on our team has code like that, and when new guys come in and point them out, we just sigh and say "yeah it would be great to rewrite that knowing what we know today". But budgeting time for that is not easy.

Edit: Also, like others said, I think you need to adjust your expectations. Working with code like that is life, and you should appreciate the fact that you, with your outside perspective and youthful energy can make a change for the better. But it's going to involve lots of refactoring and test writing.

The "Legacy Code" book referenced in another post is a great overview of this. I'd say of all programming books I've read, it's one of the ones that are most relevant to my day to day work.

This is a great reply, and I want to second a lot of the points brought up.

Adding on, the original developer is almost certainly aware of definciencies in the code. My guess is that they are largely a result of rushed deadline, changing scope, and feature creep than they are the result of bad engineering. When you need to get a new build out at 11pm because you have an angry client on the phone, it can be tempting to say “I know this is bad practice, but I’m just throwing this in the controller to get it working for now. I’ll fix it in the morning.” Especially at a small company without solid engineering practices, this happens enough times and you’ve eventually got an application with no meaningful organization or architecture.

Having been in charge of an app that started to look like this, i know that I would have loved a new dev to come in and say “I want to familiarize myself with this codebase by writing some tests, and seeing if there is any basic refactoring I can do. Where is a good place to get started?” The original developer probably wants to write those tests himself, but either has too much on this plate, or doesn’t realize how much time he’s wasting by working on a fragile codebase.

All in all, as other posters have mentioned, stay positive, and see how you can clean up and improve your little corner of the world.

One last point, I might take this as a small red flag. Don’t quit over this, but keep it in mind. If management isn’t willing or able to put engineering practices first, or to let engineers do their jobs the way they’re supposed to be done, it could signal other issues.

This is good advice, especially on the communication part.

It's always tempting to use the word "rewrite" but most of the time you just want some assurance that your code doesn't break things, and a rewrite is usually overkill.

I would suggest you to add in additional time for refactoring into your new feature development. This has 2 benefits - you're not rewriting the whole project, just the parts that are relevant to what you are currently working on, and you're still pushing out features.

It sounds like most of your refactoring work is in code isolation / scope management and creating tests.

> Then give them a few options with trade-offs.

I had (well, I’m in the middle of it, so have) to fix a few bugs in a project that are the by-products of a deeply flawed architecture. I came to my boss and explained a handful of ways that I could potentially solve the problems, and made it really clear that the best way to go would be to completely redo this one part. He agreed with me, though he wasn’t happy about how much work was involved. ¯\_(ツ)_/¯ Hopefully your managers will appreciate you giving them options.

> Hopefully your managers will appreciate you giving them options.

Take this one stage further, taking solutions to your manager is worth 10x taking problems to this manager.

For example I work with a codebase like this. It is over ten years old, have multiple people working on it, many learning or of differing abilities. Frameworks have been used and over time their limitations come to light. Often people have been band-aided something to save time, because they have been under severe time constraints. Large swathes of it are almost superseded but not quite. The purpose of the software has subtly shifted over the last decade.
you should ask yourself a few questions.

1. Is this code in production already making profit? 2. How often is this code updated? 3. Is it profitable to fix that code or just to learn from that experience and move on?

If someone is still confused after reading these, ask yourself: Will the profit I gain from leaving this alone allow me to replace the entire module in a larger refactor later?
at the beginning of my career I read somewhere if it ain't broke don't fix it. If that is making money and you can black box it, then do not fix it, for sure you could always add some test around the black box and then move on. Try to create new software outside of that box that reflects the same ideals that you would have put into "refactoring" the "bad one".
Yah i went to a big name host and found the same thing. I was fooled into joining because I met with a data scientist and an "experienced web developer" without actually looking at their code. Long story short, 2 years later it was the most frustrating experience ever and I left, hating the code the entire time. I was paid a lot and the people were cool so that made me hang around but the culture promoted hanging on to legacy code and creating scenarios where the people in charge fostered chaotic code practices by not giving a shit and always moving on to the next thing without ever cleaning up after themselves. I would recommend you to leave sooner than later as it will not get better unless you are the one that does it all or gathers some like-minded people to go forth with you but really that's too much effort IMO and you should just bail to a better scenario when you can.
> I was fooled into joining because I met with a data scientist and an "experienced web developer" without actually looking at their code.

Is it typical to be able to look at a company's code before signing up? After having a similar experience, I wish I could make that a standard part of my interviewing process. (Brief backstory: I would never in 1000 years have taken my first development job if I had seen the code first, but HR and the carefully selected engineers who could tell positive stories gave me a false impression of what was going on.)

When we first identify partners or clients, the interview is not unlike a job interview, but one where both parties are the applicant and interviewer. I cannot count the times when someone from the other side tells me about best practices in coding, CI, covering tests and version management, after which, on inspection of their codebases, they actually do none of these things. The guy at the meeting stage was a higher up tech manager/C(TI)O usually who read all the books and articles but the team is not following those same practices because of various reasons (usually intense time pressure).

We now have to demand to see the codebases we are going to work with/against first. Even if we only touch the API in some cases; if the API is built on quicksand then we risk spending a lot of time building something that is not viable but that might not be immediately clear.

> Is it typical to be able to look at a company's code before signing up?

I guess it is not typical, but at one company I interviewed for I had a day for implementing something (a small feature and some unittests) which allowed me to check their codebase. I liked what I saw and worked there for some months.

Is it buggy? Is it insecure? Is it slow?

If the answers to those questions are no. Then you the problem and you should look for employment elsewhere. You are unhappy in that job, and you rewriting the codebase would potentially make the above questions answer to a YES, inflicting damages in the company.

Now, if the above questions have yes as an answer. Talk to your manager, explain how it won't scale, how it is hackable, and the bugs you found - and get the blessing to make things better!

Do not badmouth the previous maintainer/author you do not know the circumstances that led them into creating such a codebase.

Somebody fathered a legacy codebase.
Only successful applications have the pleasure of getting old.
"Successful" by literally any measure.
I'm not sure about "any" measure, the average startup probably has no surviving code in production.. Even the average in acquired startups, if we count acquihires..
Success, in this context, means having solved some problem for a meaningful length of time.
That doesn't exclude anything. Code can exist to pad resumes, feed paranoia, and bolster egos, manipulate people, or simply because someone can't admit their own mistakes. Anything can be a solution to a problem.
Yes, those things do happen.

However, that isn't what I meant by the word "problem". I was talking about end-user problems.

So you're saying they speak from experience and know whereof they speak.
All code is legacy, the only code that’s not is the code that’s not written.
Someone's a bit touchy on this subject. Is there a reason you're using a throwaway to voice this opinion?
Hard to guess their motives but it is easy to click on their username and see that they post a lot from it.
This seems like a great post to vent a little bit. I'm definitely a bit touchy on this subject.

I like to think I'm pretty good at programming, development, and generally architecting solutions. I don't have a lot of experience, but I have a bit of talent and spent a lot of free time learning. Solving problems with computers is something I'm passionate about.

I started this particular project without any idea of what it was (okay, they told me what it was, but it turned out to be something completely different). When we did a kickoff it was myself, two other developers (who both said during the kickoff they didn't want to be on this team, and wanted to go back to admin'ing MSSQL databases), and a non-technical TPM (last time he touched a terminal was a decade ago, and he wasn't particularly interested even back then).

I ended up doing pretty much all the work. My PM would CC me on emails, I'd write the stories, he'd help prioritize them, and I'd do them. The first few weeks they wanted three services stood up and managed in an automated fashion. I got it done, it wasn't pretty. Hell I hadn't even figured out a DNS scheme, but this had to get done so other teams would be unblocked; it was the development account so I wasn't too worried about rushed work.

Then we got more requests from other teams, and vague requirements from the infosec and governance teams. Then the board that reviews new technologies shot down our (my) requests to introduce automation services like Ansible Tower. Then the AWS team shot down our request for multiple accounts, one per environment.

At this point the Cloudformation isn't scaling, I beg and plead for some time to freeze feature development and move to Terraform. I asked for 3-4 weeks, and was given 4 days. This was the one chance to move to Terraform though, otherwise we'd be using Cloudformation for the foreseeable future. So I took it, deciding I could rush through the Terraform rewrite, because then at least we could refactor it later during downtime.

Next thing you know a year has gone by and we're going into production. Everything on the devops end goes pretty smoothly. My velocity is crap though, due in large part because of the shitty rushed work, which it seemed was all I was capable of.

A few months after go-live, we finally get a real TPM, which was a godsend. I was moving to another team at this point, and so his first order of business was to replace me with two new guys. I spent a lot of nights interviewing and a month afterwards helping them get up to speed. I and the new TPM gave them cover that month so they could embark on rewriting the Terraform.

They ignored my suggestions on how to refactor it, which is okay, I was leaving the team, it was their code as now. But it was hard, hearing them laugh at the code behind my back, saying how bad it was. Never giving me a chance to justify it, or even reading the commit messages, to understand why it was done that way.

I'm off the team now, and while I recognize I left a lot of legacy code behind (which I'm not proud of), it wasn't just me who created it. It was also the business who said time and again development speed was the most important thing.

That's how one legacy codebase was created. There were a lot of things I might have been able to do differently (mostly politically), but I truly believe I did the best I could with what I had. But what do I know? My new TPM seemed to agree with me, but maybe he just didn't want to make an enemy. Perhaps I could have headed it off if I'd said the right words to the right people. I don't know, will never know.

This experience is why I don't make fun of others solutions. Somebody put effort and time and thought into it, and I guarantee (in most cases) I don't have that context to properly evaluate it.

> reading the commit messages, to understand why it was done that way.

that's assuming the original authors used version control, committed often enough to leave meaningful commit messages, and bothered to explain their decisions.

pretty much every code base i've taken over in my current role have consisted of a single posting commit with zero documentation.

Given the context, I think the individual that you're quoting said that because they did do that within the commit messages.

And outside of the one place where I was the person to introduce source control to the organization, I've found commit messages to be pretty telling. Most developers tend to let their feelings pop out in their commit messages, and too when and how often they're committing.

In your particular case, sounds like either a junior developer, legacy systems, or a sole developer.

I feel like this is how most legacy code bases are made.

> Never giving me a chance to justify it, or even reading the commit messages, to understand why it was done that way.

This is a surefire way to re-introduce bugs that were fixed ages ago. Understanding why things are the way they are is the first order of business when working within a legacy code base. Was it done this way because the obvious way has a non-obvious edge case? Was it a requirement from the users? Or was it just the fastest way to do it at the time?

You have to have a certain mindset to effectively work on legacy code, and this isn't it. Most more junior developers I've known have a "rewrite" oriented mindset, meaning they don't know how to work within the constraints of what exists and refactor piecemeal. It's a hard to learn skill, generally learnt the hard way.

Thanks for sharing this. Venting is good, and in this case a win-win, since this is good info (very relevant in a thread about encountering "bad codebases"). Hopefully OP sees it. You could well be "the other developer" where OP is.

Open question: how does one fight against what's been described in this comment? What specific sorts of communication skills? One thing that comes to mind is learning when and how hard to push-back, and how to argue with force when necessary.

The reason I ask such a specific question is because I'm not great at confrontations. I don't dread locking horns, but I'm not good at it. The more force I tend to apply, the more crass and less refined (okay, rude/arrogant) I come across, entirely unintentionally. Diplomacy seems to me to equate to "die a bit more inside, burn some more of your own wick to deal with the frustration, don't say anything, and wait and see how things work out". So I end up not engaging at all. I know I'm missing something huge here and I don't know what it is.

You really can’t, it’s not productive to assume this a skill you need or is beneficial (although it can be) and if people pick up your code and joke, laugh, or belittle without context, as in this case, it’s not your fault, don’t let it effect you. You’ll find the vast majority of developers are childish and immature, and not very good at their jobs, that’s been my experience at least.
Right, duly noted.

I'm actually speaking completely generally though; I'm falling apart at this universally speaking. Perhaps I just need to learn how to debate?

When I'm presented with a context in which I need to prepare any sort of defense, 51% of my brain will sometimes go silly, and I'll get really anxious and irrationally fearful and tense up. Things rapidly go south from there; the biggest side-effect is that my memory completely shuts down, meaning that I cannot remember a) any of the things the other person said (so I cannot form an effective defense), b) any of the things I said (so if I say something incorrect[ly] I won't remember) and c) the way I say what I say, which means that my tone of voice might be off and I'll basically be too spaced-out to notice. The resulting arguments are almost comical in their narrow-focusedness, with the resulting back-and-forth many many degrees away from whatever the original point was (which typically gets lost within the first few seconds of conversation).

This is probably due to autism and some related undiagnosed anxiety disorder, but labels aside I've never really known where to start tackling something like this. I've given up on mental health support, which only has its own agenda (I don't want the brain-fog of drugs, so all the departments could care less), I just want to brain-hack my thinking onto the right track and I've no idea how.

FWIW, this is one of the reasons I'm actually reluctant to get a job, so I'm yet to get practical experience dealing with real-world issues.

Make/take notes. Sometimes the act of writing the notes helps your recall later. If you feel that you still can't recall your notes from memory, then refer to your notes and ask to delay any debate about the topic until you have them in front of you.

Your recall may improve if you hand write your notes versus typing them out.

> Open question: how does one fight against what's been described in this comment? What specific sorts of communication skills?

This would be worth its own Ask HN, if it hasn't been posted before.

A software project can be fast, reliable, and secure while also being extremely poorly engineered and extremely difficult to maintain and extend.
Not a large one.
"There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies." — C.A.R. Hoare, The 1980 ACM Turing Award Lecture

Always loved this quote.

Why can't you badmouth the previous developer? Sometimes they were simply shit developers and wrote large quantities of shit code. Circumstances be damned, I've seen a few developers that should outright find a new career.
Generally because once you start badmouthing a person, it quickly gets into politics rather than being a technical discussion about the problems you're trying to solve. And with politics it's generally less about what you know than who you know, so the person who's had a chance to build connections in the company will probably come out on top.
If you ask me, this is a pretty awful approach. "Bug-free", secure, and fast are not the only metrics of whether or not a codebase is worth keeping alive. Some codebases are so obscenely dangerous that you really shouldn't be giving a shit whether or not it "works", because it's only a matter of time before it doesn't. There are code practices that are inexcusable under any circumstance. Sitting on a fucking nailbomb when it's in your power to change it because you don't want the headache of having to push for a real solution will catch up with you in the end.

I'm not saying that you have an option in a do-or-die situation where it needs to be done in a couple days. I'm also not saying that you should subvert or defy management to execute a massive overhaul or total rewrite. I am saying that if you understand a system, know that it's fundamentally flawed, and have a window to fix it (even if it's a really tiny one), but choose not to, you are part of the problem. The standards that software developers are held to in terms of quality are an absolute joke, and the "it hasn't completely imploded our business operation, so don't even think about fixing it" mentality is where those standards stem from.

You have identified 3 important non-functional requirements: robustness, security and performance.

But what about:

- maintainability, extensibility, reusability, configuration

- mean time to detection / mean time to repair during an incident

- bus factor, cost of adding more developers, documentation

Code can still be problematic in terms of those and I think that would be closer to what the OP described.

Consider you have 2 cars: both are reliable, but during maintenance one of them requires you to buy rare and expensive replacement parts that you need to import yourself, only one shop in the entire city can work with it and it takes 2 weeks to get the work done. Which car would you rather have after going the process I described 3 times?

Popularize the value of tests. Test, refactor, repeat. 2 years of legacy spaghetti isn't really that bad. I work for a company whose codebase is at least 14 years old in places, and there have only been serious testing efforts for 2-3 years.

Chances are, the code is a mess because nobody who knew better was empowered or motivated to advocate for a better way, but you have a hidden opportunity to be that hero.

Good luck!

> I've already made some comments about rewriting it and the response was basically "ok".

Do it.

Gradually.

Rename. Simplify. Reduce. Enhance. Test. Slice and dice.

Embrace the shitiness. Accept it. Own it.

It's your playground. Sharpen your skills, and lead them to the promised land.

It could be worse. You could face major resistance and people issues. Appreciate it.

This is an opportunity for you to kick a billion miles of ass...

I'd start with writing tests. That way you're more likely to notice if you break something in a distant part of the code.

Also see if you can make a to-do list. This will help make your request concrete to management. As you cross items off it will help them see that you're actually getting work done. And, it could help to motivate you if you feel like you're "just rewriting the code".

Before going to management to talk about someone, I would talk with that person. Maybe he/she hates the code as much as you do. Sometimes, shitty code just happens. Avoiding it is part of the job, but not always a possibility.

And if you have the option to rewrite it and you think you can do a good job, go for it and good luck!

is improving old code really what you want your career to become? this is a selfish question, but you need to put your own needs before that of the company. you are not a charity. they are selfish. be selfish.
One thing you can try doing is to rework sections of the codebase gradually over time as you change them. Don't touch code that is working and doesn't need to be updated, but if you are working on a feature in one corner of the codebase, see what you can do to improve that part of the codebase.

This is easier to deal with both in terms of selling it to management and making sure you don't actually break the whole system compared to a full scale rewrite. I've made that mistake before and it wasn't fun. As others have said, code that's in production and works and is making money has value. The "cleanness of the code" is not something business owners care about, unless it causes problems.

There's a book called "Working Effectively with Legacy Code" by Michael C. Feathers which I heartily recommend.

I got it a while back when working on a similar sounding codebase and it was very useful. It's got chapter headings like "My Application Has No Structure" and "I'm Changing the Same Code All Over the Place".

If your company has a books budget get them to buy it, but I'd personally drop the £35 it costs on amazon given how useful this has been to me over the years.

Yes, so good. Martin Fowler's Refactoring is an excellent companion to Feathers' book.
It will be worthwhile to know that a second edition of that book is expected to come out shortly.
This book was written for OP (and many others). It specifically addresses the "there are no tests, what do I do?" concern.
Is there a chapter on what to do if your coworkers don't initialize variables? I just inherited a steaming pile of legacy where they didn't and I'm struggling to understand how they got it to run at all. At least I'm starting to understand why we held off on the spectre patches.
Not explicitly, no, but it does have some techniques for reading code that might help?

Do you mean global variables? I guess it entirely depends on what language and framework you're using, but trying to refactor things to have less global state is generally for the best.

This sounds normal.

Back in the 90's and early 2000's, almost nothing had automated tests. Miraculously, things still got done by manually testing.

On the other hand, I worked at shops where every getter and setter had a test. Not much got done there.

> Miraculously, things still got done by manually testing.

That is still very normal and not very miraculously considering it happens all the time and very large companies run on this practice.

Although I am a fan of automated tests, I work with enough codebases that are robust and have been working for over 10 years that have no tests and others with a lot of test that are still fragile and miserable to work with. It is not all that black and white but you imply that as well with the getter/setter tests.

Yes, I was being sarcastic with the "miraculous" comment. The right answer is definitely a middle ground...
Grass aint greener anywhere else. Prioritize learning, get better, increase the level of job in your range, get better job, loop until manager or self employed (at which point you'll have nobody to blame for your tech debt but you!)
Welcome to the real world.
You don’t need anybody’s permission to gradually add tests and improve the code base little by little. Don’t ask for permission, just make it a little better every day.
If 1) there's a solid engineering case to be made that this code is bad, 2) the code does something that's important, and 3) the company doesn't want to fix it, then you can be confident that the company also isn't interested in investing in the things that you as an employee would want them to be. I would expect work in general to be unenriching, raises to be smaller than at other places, and other benefits to be not as good. This could be an early sign that spending time with this employer is bad for your professional growth.

Edit: definitely kick the tires a bit by seeing if this situation is typical for the company, or if it's an outlier.

I think it is a good trait that you care enough about your work to feel this much frustration. Change though, is often hard to achieve because people tend to be stubborn. To provide more useful feedback I think you should mention what is expected from you at work. Are you supposed to be working on new features in this project or just maintainence?

Regardless of the exact situation, there should always be a way for you to work on your craft. It sounds like you are doing a lot of refactoring now and that could be quite rewarding, even without tests. If you find yourself trying hard to improve the environment and feel like it is to no avail and that no one is listening, while simultaneously feeling like you can’t leave the job in the short term, you might want to think about how to take advantage of the dead time at work to learn new things or do other activities that improve your skills.

1. take the initiative, fix what you can, quickly and quietly. 2. practice emotional detachment 3. think of the work as manual labour 4. re/read people-ware 5. this isn't personal 6. if you're good at it, see 1. 7. if you're not, look for the next job, where you can write code from scratch 8. what is the problem, really
You need to make a choice:

1. Try to get the political will to change it, then lead a change. This is essentially impossible unless you're a respected senior developer, and even there it is hard. There is a lot of advice out there, but the primary thing I've seen work is this: Complete feature freeze. API-ify the backend with heavy tests through the API. Have the presentation layer slowly shift to the new API. Once the API is complete, delete all the other backend code. Refactor the presentation layer with tests as you go.

2. Accept that the codebase is shit and look at your situation realistically. If you can't switch jobs (visa issues, etc) you need to accept that this is the way it is at this company and don't grumble about it. Spend 20% of your time making tools that help you compensate for the shit quality of the codebase; admittedly this is easier on non-Windows projects. Even so, making a small tools for disorganized projects really helps make you look super pro, even if the code is doing most of the work.

3. Quit and work somewhere else with better people and a better codebase.

Out of all the reasons I advocate TDD, from cybersecurity to QA, they pale in comparison to employee retention. Keeping a codebase clean over time requires tests. It just does. If you don't have tests things ossify. I don't write tests for ad-hoc querying data, but I always write them for long lived projects and I refuse to work on established projects that don't have test suites (or direction from on-high to add them).

> "The job basically turned into something I hate - I'm just rewriting the code..."

Yes and no. Let's be honest, we all rewrite (i.e., refactor). It's just that we do it to our own code.

Long to short, this might not be what you enjoy but it has the potential to be a great learning experience. Doing code autopsies can teach you more than you realize.

Should I just go and basically say that this person did a bad job?

No, absolutely not.

Look for the positives in what has already been accomplished, then sell them on the idea that "it can be even better."

Since it sounds like they are fine with you making improvements, just take it one step at a time and keep at it.

The code base that exists took many hours to develop. You wouldn't have a job at all if it didn't exist in some kind of functional state, no matter how bad it is.

Don't brag. Don't position yourself as some know-it-all hot shot. Just keep improving things and let your work speak for itself.

Ideally, you want to get good at explaining why the change matters in terms that make sense to the non technical folks involved in making decisions.

Do make sure they know you did the work. Don't let someone else get credit for it.

Bookmark this page so that 15 years down the line in your career you can reflect on it. You will have delivered a working software product against all odds, under impossible budget and time demands. Finally they let you hire some help and instead of getting busy helping writing tests and refactoring he starts thinking about the best way to throw you under the bus to your superiors.
This should be the top comment. At my company it is amazing how clueless young graduates play politics from day one, while doing no real work other than going from conference to conference and self-promoting on Twitter.
> "Finally they let you hire some help and instead of getting busy helping writing tests and refactoring he starts thinking about the best way to throw you under the bus to your superiors."

Here's what actually happens.

By that point in a project's lifecycle, that's not what they usually ask of the new hires. People are usually tasked with fixing bugs/maintenance, and implementing new business logic. Both of which are extremely challenging and stressful when working on a project that comes with no tests, or documentation.

Your actual task as the new hire is to start generating more value for the company, but that's so much more challenging when you have no way of validating your solutions, no infrastructure to rely on, and no metrics or documentation to consult. At that point, being the new hire, you're taking a lot of heat for not getting things done on time - mostly through no fault of your own. At that point, "wanting to throw you under the bus to your superiors" is a very natural response - it's a defense mechanism, you're (rightfully) frustrated. You're between a rock and a hard place. At that point you're no longer doing software engineering, it turns to politics/coverups/fire-extinguishing on a daily basis. Can you not relate to that?

Welcome to the world of professional programming. Situation normal at many many companies.

The best advice I can give is DO NOT start a stop the world rewrite! and to look at the SOLID pattern and implement it using the STABLE strategy.

-Smell your code -Tiny changes first -Augment your tests -Back up -Leave it better than you found it -Expect good reasons

Full credit to Sarah Mei

https://markheath.net/post/stable-tactics-for-writing-solid-...

1. Stop "repairing" it because you're guaranteed to introduce bugs and regressions. You haven't learned it well enough and can already sense the fragility, which is why you're anxious.

2. Relate your impressions to the person in charge: "The code doesn't seem to follow best practice and appears fragile. You think there may be technical debt that needs to be addressed sooner than later."

3. Until you're confident enough that you can pitch a comprehensive redesign and rewrite, wait for the person in charge to direct you towards specific repairs. When they direct you towards these specific repairs, they will anticipate regressions and instability. They'll see you as working through issues, not causing them.

4. Repeat step 2 periodically and with greater detail until you're ready to make the pitch in Step 3. Don't rush it.

The alternate solution: leave and let somebody else deal with the problem. Some people are comfortable working around fragile and wonky code; some people get really stressed out. You don't need to work in a job that's going to perpetually stress you out.

I love your answer because it calls out the perception of what you're doing. It's so important to frame what you're doing in a positive light, otherwise you'll fail, whether or not you make the codebase better.
> Some people are comfortable working around fragile and wonky code

Yep, because I have worked with very bad codebases over the past 25 years, I actually enjoy the challenge. For me it is more rewarding than working with pristine and well managed code bases.

Ditto.

I was explaining greenfield vs. brownfield to a co-worker (non-developer) between periods of fixing a previous, junior, developers code that was essentially creating a seemingly infinite number of pages on our site.

Keeping in mind the above, I also know that deadlines, changing requirements, and lack of a clear goal (due to the previously mentioned items), lead to this. Had I not worked with them, my decade and a half of experience would have strongly suggested that such was the case.

When it comes down to it, some people prefer working on new projects, and some people prefer supporting and polishing those once-new projects. But to really succeed you've got to be able to do both, to some extent.

Go slowly and look carefully at things.

No matter how insane a code base looks, (unless it is totally inoperable) it is meeting a lot of conditions that are more important than whatever you are fixing but won't be recognized as important until you break them.

Those conditions built up over time and were changed irrationally by business decisions and hit or miss communication. A lot of demoralizing for anyone who was trying to keep standards while meeting requests.. Don't beat up the past maintainers for a past you can't know in much detail.

Maintaining old code can be fun though and is a more interesting puzzle game than most new development. Just try to stay emotionally neutral and unattached to anything about the code besides the specific challenges as they need tackling.