
Ask HN: Working with a monolithic codebase - throwaway047292
Junior dev, about 6 months out of college at a smallish (~20 engineers) software company.  Monolithic java codebase that all runs on a single cluster of app servers.  I&#x27;ve been feeling frustrated lately and wanted some advice.<p>The most common comment in my code reviews:
&quot;You&#x27;re reinventing the wheel - we already wrote something similar. Take a look at [X], extend it a bit to fit this use case, and toss what you have.&quot;
Since X is always undocumented this involves sleuthing + picking senior dev&#x27;s brains.  The process slowly repeats until my feature eventually converges onto a configuration of existing components, with as little new code as possible.<p>That&#x27;s great for the business but not much fun for me.  It means that to do a task that could be completed from scratch in X hours, I must spend X^(size of our codebase) hours grappling with other people&#x27;s ideas, solutions, and mistakes.  It means my thoughts must be bent to fit some pre-existing shape, which eliminates the need for my thoughts, and suggests they should be permanently replaced with those of my predecessors.<p>Is this actually the sign of a good codebase?  Should I be deriving pleasure from this?  Is this what software development is?
======
partisan
If your co-workers are telling you that you are reinventing the wheel then you
are likely not taking the time to understand the framework that has been
developed over time.

You are a junior dev. They hired you to invest in you and grow you. They pay
you in dollars, not pleasure. Your day 1 contributions are likely meaningless
in the grand scheme. What they want to see is that you can read and understand
existing code and that you are a team player. Any code monkey can go in and
write functions for validation or logging, but if I am paying you to
understand HOW you should do it, taking advantage of the (hundreds of)
thousands of dollars of my investment, then I would be pretty frustrated with
you if you rolled your own. I would be further frustrated if you disregarded
my attempts to point you in the right direction.

You are more likely going to have a positive impact by suggesting changes
within the framework they are providing you than creating your own. Learn and
understand what the code does and WHY it exists and then you will be able to
see what can be improved. Coming in and saying that everything is wrong and
persisting in doing your own thing, at your employers expense, will probably
leave you without a job.

To satisfy your need to learn and be creative, work on a side project of your
choosing. You shouldn't expect your day job to give you 100% of your career
development. A large part of it is on you and whether you are passionate
enough to invest in your own development on your own time.

------
a-priori
One of the important lessons you need to learn is that code is a liability not
an asset! All else being equal, from a balance sheet perspective having more
code puts the company in a worse situation.

Your job as a software developer is, roughly, to deliver maximum business
value with minimum cost, and that includes writing minimum code to accomplish
the task. That is what the senior developers are talking about when they're
saying you've written too much code.

It does sound to me like they've got a well designed system if you can add new
features simply by making a small modification and some configuration to the
existing code. As long as it's also well tested and well documented (that may
be lacking...), you've got the ideal codebase: one in which you can add large
amounts of business value with only incremental changes.

You mention that this is "great for the business but not much fun for me". I
think this is a sign of inexperience. Part of what makes something fun is how
difficult it is. If something is too easy it's boring; if something is too
hard it's frustrating. In the middle we find things fun. The reason writing
lots of greenfield code is fun for you is because it's easy. Understanding and
modifying existing code is harder, and that's currently too hard so you find
it frustrating. You need to push past this stage to improve as a developer. As
you get better, it will become easier to work in existing code and will stop
being so frustrating.

~~~
vbtemp
> One of the important lessons you need to learn is that code is a liability
> not an asset

I cannot upvote this enough.

~~~
RivieraKid
This is simply not true. If code was an liability, it would be profitable to
transwer owenership of it to other people. I haven't noticed any software
company doing that.

~~~
a-priori
In software, there's a whole industry around this: we call it SaaS and/or
cloud services. And in fact, it's basically what it means to be a 'services'
company. Your customers are paying you to move that liability I mentioned onto
your balance sheet instead of theirs.

------
alexandercrohde
My suggestion is:

1\. Let go of your frustration for now, a company is an incredibly complex
machine and you need to invest more than 6 months learning how it works before
people take your criticism seriously (I know this can be hard). Also, some
people like to 'grill' the newbie as a right of passage, you may be
experiencing this.

2\. Acknowledge that code-reuse is awesome. It's great that there's reusable
functionality, part of your job is memorizing the handy tools at a company and
if they're good enough, rebuilding those tools later at your next job.

3\. It sounds like you're frustrated that you don't find out about existing
libraries/functions/classes/tools until your code review. That seems like a
reasonable concern. Maybe next time you have a project come up with a rough
plan and ask a senior developer for architecture-level feedback before you
start coding.

4\. Don't feel bad. You don't need to be a hero or change the world. If you
mimic the senior engineers and try to fit in that'll go further than studying
engineering theory, writing perfect code, or documenting the codebase. Once
you're accepted into the group they'll be much more receptive to your ideas on
how fix things.

~~~
noxToken
> _It sounds like you 're frustrated that you don't find out about existing
> libraries/functions/classes/tools until your code review. That seems like a
> reasonable concern. Maybe next time you have a project come up with a rough
> plan and ask a senior developer for architecture-level feedback before you
> start coding._

I couldn't agree with this point more. When I first started, my team lead gave
me a rough plan to add new features so that I wouldn't go in blind. Until I
could stand without the support of others, I drafted a quick plan of action to
get the task accomplish. This let my team lead know how I was planning on
accomplishing the task while allowing them to point out existing code that
would take care something I would have written.

It seems like unnecessary overhead, but the 5 minute conversation up front
saves more time down the road.

------
eecks
You just need to chat about the solution before you start coding - which is
the normal way to do it.

You: I have the task of X and I'm thinking of doing Y to do it

Other dev: Oh, we have W for that, it might help

You: Cool, I'll check W out

------
geofft
Are you talking to senior devs _before_ writing code? "Hey, I'm going to
implement such-and-such feature, I think this involves building such-and-such
classes/services/etc., is that a reasonable way to go about it?"

Even with the best documentation, there aren't very many functional projects
(either companies or open-source projects) where the expected way of
contributing is not to talk to anyone until you open a PR.

~~~
Yhippa
I like this. I've been developing for a while and still spitball ideas with my
coworkers to see if it already hasn't been done before. Or if my ideas are
just plain crazy.

------
jmilloy
6 months is not very long, so it's not surprising that you don't know what's
already available in your company's codebase. That's true whether it's
monolithic or not, in Java or another language, on a single server or a fleet
of raspberry pis flying around on drones. In fact, assigning you tasks that
involve tweaking existing components is _exactly_ what most companies will do
in order to get you familiar with the codebase (and style, process, etc) while
they they get familiar with you.

* Don't worry if you have to replace parts of your code. That's just part of the process, especially if the existing code is undocumented and everyone knows that. The code reviews are working.

* However, if at all possible, get feedback early in order to skip straight to implementing the feature with existing code. You'll finish features faster, get familiar with the codebase sooner, and hopefully move on to more interesting tasks sooner.

* Document existing code as you discover and use it. This is technical debt that your company needs fixed, and you're in a great position to help with that.

In school you get to write a lot of our own code from scratch with our own
ideas, and it's fun. Some developers pump out code by the minute, even
implementing the same thing over and over again in their own code; it's fun,
and there often aren't repercussions for that in school. But code re-use _is_
good practice. I love days when I produce net negative lines of code in an
existing codebase, while adding a feature.

Not every company offers the opportunity to implement your own ideas from
"scratch". In fact that's somewhat rare. If this is the only coding you enjoy,
you may need a new company, but you may just need to wait a bit longer at your
current company. A good advisor/boss will be able to have a conversation with
you about expectations (going both ways) for the first and second year. You'll
want to find out if your company can eventually provide the kind of projects
you want, especially as you get a better idea of what those are.

------
eCa
The problem isn't that you have to use/extend existing code, the problem is
that it isn't documented. I'm guessing there is a lack of knowledge sharing
between the developers.

Like others have said; instead of writing the functionality from scratch, try
to understand the existing code and document it.

> The process slowly repeats until my feature eventually converges onto a
> configuration of existing components, with as little new code as possible.

In other words: "The process slowly repeats until you know the codebase".
Also, less code brings less bugs.

> I must spend X^(size of our codebase) hours grappling with other people's
> ideas, solutions, and mistakes.

Learning to understanding how other people think is crucial, and its better to
learn from the mistakes of others than your own.

> Should I be deriving pleasure from this?

Hopefully, with time. But you are more supposed to derive a salary from it.

------
fmsf
> The process slowly repeats until my feature eventually converges onto a
> configuration of existing components, with as little new code as possible.

Adding less code as possible is good. It means that things are well
structured. The speed that you want seems like you want to hack your way
through and just increase maintenance time. That is what software development
is.

If you feel some piece of code should be refactored and re-written /
extracted, then that is another completely different case. Check what is the
value and impact on doing it, both short and long term, and expose your
rational to your team.

For me the biggest signs of a good codebase is having a clean build system and
proper testing.

------
smrtinsert
Other people have put it very well here. Welcome to the job. Beautiful code
from scratch is for your own time. You'll see that you'll learn this
"monolithic" code base over time and that eventually you will play it like a
violin and it will be somewhat enjoyable.

If you want to write code from scratch and just blaze forward all the time
join a startup. Less guaranteed job security but more fun for sure.

------
dustingetz
This is all codebases ever, including all open source codebases. You have to
learn the codebase before you can contribute effectively to it.

------
such_a_casual
If the software is undocumented, then document it as you read it. At the very
least make sure that you are documenting your own modifications. In any code
base, you are going to need to dedicate the time to learning what that code
base is.

Before you do X, you should always ask someone if they are aware whether or
not X already exists in the code base.

This is true outside of the work setting. If you are making websites for fun
in your spare time, you are likely to spend time learning a framework such as
node or django. If you are making games you are going to learn some tool like
Unity or an engine like unreal or source.

Imagine if you had a project where you defined 20 different functions for
requesting the html of a webpage, each doing something slightly different.
Think about what kind of a maintenance nightmare that would be. You are
suddenly required to implement a proxy on all requests, but doing so breaks
half of your functions. You can't just scrap them, because each has a nuanced
use (since you were too lazy to update your existing function(s) to fit your
needs).

You would never do that in your own project, but that's exactly what you're
doing with this company's code base.

"It means my thoughts must be bent to fit some pre-existing shape, which
eliminates the need for my thoughts, and suggests they should be permanently
replaced with those of my predecessors."

No, it means your thoughts must bend the pre-existing shape, which eliminates
the need to create the shape yourself, since that was already handled by your
predecessors.

Your point of view is a lie. Do you program on an OS you wrote yourself from
assembly code, in your own programming language, on your own custom built
hardware, with no libraries or tooling?

Musicians do not reinvent thousands of years of musical discovery, yet they
manage to find immense pleasure and creativity in their work.

If you have done very little programming outside of college, you should see
other people's code as a treasure trove of information. Just as musicians find
inspiration in other people's songs. My last tip is to revert to pencil and
paper when you are having difficulty understanding someone else's code.

~~~
seren
I also believe this is primarily a communication issue. It is bound to happen
a few times when working in an unknown codebase, but if you feel this is
systematic, before writing a single line of code, just discuss with the code
reviewer what you plan to implement. It should be a matter of seconds for him
to tell you if it makes sense or not.

------
jdbernard
Sometimes it can be helpful to try and fast-forward through time. Imagine you
are writing your own new code. You've got it working well. You've spent some
time thinking about it, so you've left room for growth and made it extensible
so that next time a new feature comes along you don't have to rewrite the
whole thing. Then a new dev onboards and starts redoing things you've already
done.

Right now you're the new dev. Yes, you are going to have a lot to learn about
code that's already in place. Totally greenfield development is fairly rare.
You don't have to learn the whole codebase (almost no-one does in large
projects), but it would be wise to solicit input about where you should start
looking before writing brand new code for a new feature.

> That's great for the business but not much fun for me.

That's why we call it "work" and not "play." :)

------
romanovcode
To tell you the truth it has nothing to do with monolith. You think if you
write it in microservices because that's what's "hip" now you're very wrong.

~~~
Cthulhu_
Besides, the microservices architecture doesn't mean you should re-implement
features (like the framework / library type of functions). Microservices have
the same amount of code, if not more, than the monoliths they're supposed to
replace, and likewise should employ code re-use / not re-invent the wheel as
much as possible.

~~~
romanovcode
Yea, exactly. Company I'm working with now made the mistake of following the
hip. Basically management were crazy about node and microservices.

Went from PHP "monolith" with couple of services to Node.js using
microservices. Jesus what a mess, our previous stack was 10x cleaner. Not to
mention company now spends thousands of dollars every month for all the
new/cool AWS stuff.

But hey, they pay me so I'm not complaining. :)

------
codingdave
In addition to what everyone has already said about asking before coding and
learning the codebase before writing from scratch, you could step up and
document these things as you learn them. Not only might it help in the
learning process, it will make it easier on the next guy who gets hired.

~~~
khedoros
This is what I was thinking. When I started on my first project, there was
already some documentation of the core classes in our codebase, what they do,
how they interact, etc, and it was incredibly useful to me as a new college
grad. It gave me a direction to look in and provided structure to the
questions that I still inevitably had to take to the more senior developers.

------
lwf
Greenfielding when there's already existing code to do what you want adds
bloat and allows for regressions. Using previously-developed frameworks for
e.g. validation, can help reduce bloat, and can help ensure the codebase is
maintainable for the long run.

Think about it: do you want to have 5 separately-implemented code paths that
all accomplish essentially the same thing, or one generic codepath that
handles all the reasonable cases?

------
gus_massa
Can you start an internal wiki and document the functions?

But remember to follow the 6th step of
[http://www.joelonsoftware.com/articles/fog0000000332.html](http://www.joelonsoftware.com/articles/fog0000000332.html)

------
bflu53r
NO it isn't a good codebase (can't understand it without talking to senior
devs) and NO that doesn't HAVE to be what software development is; but
unfortunately, it often IS... try to find work at a startup, or start your
own, if you're that unhappy with things; if not, try to learn what you can
from the senior devs, and their massive poorly documented codebase. Working
with senior devs can be a drag, for sure -- I should know, I am one ;-)

------
jedwardhawkins
I'm surprised that nobody has mentioned pair programming. You may also try to
propose Lunch and Learn sessions where an expert on a particular portion of
your project teaches the rest of the team about their area of expertise (how
to work in it, architecture, where code is located, etc...). Don't be afraid
to ask someone to teach you or a group. Chances are good that multiple other
engineers could benefit from the same information.

~~~
amorphid
Pairing helps me figure out large code bases quite a bit.

------
cjcenizal
When I was first learning the ropes as a developer, I found myself in similar
situations, and it was equally frustrating (for both myself and my coworkers).
What changed was I learned how to separate myself from the code. Programming
is a team sport. You're all building a codebase together. And good code should
be objectively good so it doesn't matter who writes it. You'll impart maximum
value to your team once you learn how to cooperate. That's step 1.

Step 2 is learning how to adopt an engineering mindset. Spend time in analysis
and ask your coworkers for feedback on your approach. Critical thought should
not change from person to person. If the engineer before you applied critical
thought to her/his code, then s/he encountered the same problems and made the
same decisions you would, if you also applied critical thought. So spending
time reading code and understanding it is a huge time saver.

The critique of re-inventing the wheel isn't "hey you just made a wheel... we
already have one of those". It's "hey you spent all your time thinking about
wheels and working out all the details... we've _already done that thinking
and here it is written down_. Save yourself some time and catch up to us. We
did the heavy lifting for you."

------
dm03514
Yes If the current abstractions in the code are flexible enough to be
extended, I certainly think so. I've worked on so many projects that were so
brittle extension/reuse wasn't really an option, with out major refractors

No.

Yes, you're lucky the current code is flexible enough to be extended, if there
is good unit test coverage that's one better. For me, it is crucial to study
outside of work and have side projects

------
neogodless
I'm in the middle of reading "Punished by Rewards" and it's interesting to
cast this particular predicament in light of the proposition of that book.

 _If you 're writing code to get the reward of a salary, you're not going to
enjoy it nearly as much as if you do it for its own sake!_ Rather, you'll
enjoy less the more you're doing it due to extrinsic motivation.

I'm not sure of the solution, but I suspect you need to cast any of these
challenges, whether they are really _coding_ challenges, or rather team
communication challenges, as something you're excited (rather than anxious) to
overcome and improve your skills at doing. Forget (in those moments) that
you're doing it for a salary, but decide that, in order to later improve
strictly coding skills, you are wise to currently work on improving your
communication skills, your ability to discovering the capabilities of existing
code and frameworks, and perhaps your ability to document anything you learn
for future reference (for yourself and others.)

------
gramakri
I recommend taking an active interest in becoming a documentarian. Document
things as you go, create wiki pages. While unrewarding, this task usually
never goes unnoticed. IMO, understanding why things are the way they are makes
one a better programmer.

Not sure about you but when I had history classes in school I was totally
bored and could not appreciate it. But these days, I wish I had paid more
attention. It really is a lot of fun to know historical facts and why things
came to be and why they are the way they are.

------
Ologn
> Junior dev

> Monolithic java codebase

> "we already wrote something similar"

Sometimes it's not even them who wrote something. I was working on a Java
codebase where decimal numbers always had the separator be a period (e.g.
1.2).

In (most of) continental Europe, the character they use to separate the
numbers in a decimal is a comma (e.g. 1,2). So I coded something up to do a
location-specific separator.

Woops! Actually java.text.DecimalFormatSymbols().getDecimalSeparator() will do
that, and has been a Java core API since Java 1.1.

------
TeeWEE
Well, probably the codebase doesnt have a lot of documentation, and thats why
the 'top' engineers always tell you after-the-fact howto do it.

Next time when they point you to it.. Tell them: where was this documented.
How can i prevent reinventing the wheel later?

Also ensure that the code that they wrote, is located in a logic location.
Often it is not, and thats why its difficult to write in that codebase.

So it can mean two things: bad structured code, bad documentation, or you lack
knowledge in the codebase.

------
crimsonalucard
Everyone can write code after 6 months of bootcamp. Not everyone can read
code. You're complaining about reading code, which is 90% of what developers
do on a daily basis. 10% of what developers do is write code. With of course
the rare exception that you're architecting something from the ground up.

If you can write code but you can't read, than I'm sorry to say that you are
not a good developer.

------
spion
I think we haven't completely figured out software development yet, and its a
bit of a mess :)

Yes, this is typical of today's software development process. The codebase may
be good in terms of code quality, but it sounds like it doesn't have the best
architecture.

Unfortunately, good architecture is extremely hard. The architect has to
really think about the problem and come up with abstractions that are simple,
intuitive, orthogonal, self-consistent, universal, not overwhelming,
programmable (not configurable) and stand the test of time

Simple -> means that abstractions should only represent one thing. A rule-of-
thumb test is: if you ask yourself what does this abstraction do or define, it
should be a single item (not a list)

Intuitive -> abstractions that resemble existing abstractions that are in
common use, as well as things in the real world. (or in the problem domain)
For example, its possible to reuse a File abstraction for many things. Another
example, UI classes should mirror things that are shown on the screen; in
simulations classes should mirror the things being simulated, and so on.

Orthogonal -> abstractions should either introduce new functionality, or
combine multiple functionalities into one - never both at the same time. For
example, a function that reads settings from environment variables then calls
another function with those settings is often likely to benefit from split
into 2 functions: one to read the variables and another to glue together
readVariables and callOtherFunction.

Consistent -> an abstraction should have laws that are never contradicted
(they're factual, never changing), and users should only rely on those laws
and no other properties. The best examples of this can be found in Haskell's
standard type class tree.

Universal -> an abstraction should apply to all cases where possible. E.g. all
mappable things should be mappable in the same way (Arrays, Tasks,
Observables, etc) and all parts of the program should be able to take
advantage of that

Not overwhelming -> The human brain can keep track of up to 10 concepts at the
same time. The architect should keep this in mind and properly
compartmentalise abstractions in a way that doesn't overwhelm. The fewer
things you need to keep track of at the same time, the better.

Programmable, not configurable -> Whenever possible, good code is
programmable, not configurable. For example, a chart plotting function could
take a detailed configuration object that contains a description on how to
format the labels, e.g. { decimals: 1, units: {1: 'm', 1000: 'km'}}, could
allow the user to pass a formatting function that takes the number and
generates the label text. The second one is always more flexible and
extendable.

Some of these properties may sometimes be at odds at eachother.

A note about microservices: they're popular because they enforce some of these
properties somewhat: most small services are _simple_ , the API (interface) is
given some thought to make it _intuitive_ and _consistent_ , they nudge
towards _orthogonality_ as inter-service dependencies have a much higher cost
and are therefore avoided... However they have some downsides (e.g. they
favour _configurable_ instead of programmable, as its somewhat hard to pass
code to be called by the microservice)

------
dozzie
In order of your questions: no, no, typically.

