top | item 20124018

Absolute truths I unlearned as junior developer

1529 points| dcu | 6 years ago |monicalent.com

511 comments

order
[+] beat|6 years ago|reply
Admittedly, my first days as a junior programmer were before some of you were born, but I'm thinking of a particular format here...

Learned as junior: If you report an OS bug or some other deep problem, seniors will not believe you and assume you're making excuses for your own bugs and lack of understanding.

Understood as senior: If a junior programmer tells me they found a system-level bug, I won't believe them and will tell them to go figure out what's wrong with their code.

Learned as junior: Legacy code is hard to read.

Understood as senior: Legacy code that I wrote myself is hard to read.

Learned as junior: Technical skills matter most.

Understood as senior: Communication skills matter most.

Learned as junior: New tech solves old problems.

Understood as senior: New tech creates new problems.

[+] enobrev|6 years ago|reply
> code that I wrote myself is hard to read

This has happened more times than it probably should:

1. Arrive upon some code I wrote at some point in the near or distant past.

2. Review it to get some idea of what I was trying to do

3. Laugh at my young self for being so naive

4. Refactor or Rewrite

5. Re-realize the edge-cases and difficulties

6. Remember this being a problem

7. Refactor And Rewrite

8. Either `git reset --hard HEAD` or end up with a similar solution, but with better comments

Once in a while, I end up with a [simpler | faster | clearer | otherwise better] version, which makes this process worth while - even with the false positives.

[+] dahart|6 years ago|reply
Oh this is such a good comment!

> Legacy code that I wrote myself is hard to read.

Sometimes I don’t even recognize me as the author for a while. Realizing I’m reading something I wrote and can’t understand it without studying carefully has been rather surprising and reminds me of the old Kernighan quote “Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?”

My goals used to be to write code that looked and felt cool to myself and others, to add features in clever ways with as little change to the function signatures and structure as possible so as to not disturb the architecture. While keeping changes small is a good goal to balance, it’s always possible to be too small and add unnamed concepts and fail to restructure around new concepts when you should. Do that a few times in a row (which I have done) and you end up with architectural spaghetti code that might look clean and modular at first glance but becomes a maintenance nightmare. My goals are now to: - make code so easy to read it’s boring, because if it looks interesting, it’s probably too clever - and to identify and name all the unnamed concepts and refactor often to accommodate new features.

[+] chadash|6 years ago|reply
> Understood as senior: If a junior programmer tells me they found a system-level bug, I won't believe them and will tell them to go figure out what's wrong with their code.

My first job was in finance and I remember one time that I had a glitch on a complicated Excel spreadsheet. I checked it over, checked again and checked again until I finally concluded that the bug was in Excel itself. So I go to my boss and tell him that the data isn't ready because there's a bug in Excel. I was laughed at by the entire team. They agreed to give me $1000 right then and there if it was really a bug, but if not, I had to admit the shame. Well... of course it wasn't a bug in Excel, I just made a careless, albeit hard-to-find, mistake.

Lesson learned. If millions of people use something, that doesn't mean it doesn't have bugs. But it does mean that you probably aren't going to find those bugs unless you are doing something strange.

oddly, I did once find an actual bug with indexes in Postgres. Because of my earlier experience, I spent a lot of time assuming it was me before I finally isolated it as being a bug with postgres itself. I submitted a bug report and it was patched within a day. But still, 99% of the time, it's me.

[+] docker_up|6 years ago|reply
> Understood as senior: Legacy code that I wrote myself is hard to read.

For me, any code that I wrote more than 3 weeks, I forgot. That's why I comment the hell out of my code. The younger programmers have routinely told me "commented code means the code isn't very good." I chuckle and ignore them and wait for them to hit their mid-30s and older.

[+] kps|6 years ago|reply
Lemma:

> Learned as junior: Legacy code is hard to read. Understood as senior: Legacy code that I wrote myself is hard to read.

Lemma:

> Learned as junior: Technical skills matter most. Understood as senior: Communication skills matter most.

Theorem:

Communication needs to target the people of the future.

[+] leibnitz27|6 years ago|reply
Way back in the day, my boss made a lovely observation - 'write your code like it's going to be maintained by an axe murderer who has your home address, and nothing to lose.'

Simple guidelines to live your life by ;)

[+] robomartin|6 years ago|reply
All excellent points. I got used to filling my code with comments in the spirit of having a conversation with someone to whom I am explaining how an why. Thirty years later I can look at any of my code and quickly understand it. In sharp contrast to this I find most open source code to be difficult and laborious to understand due to the almost total lack of useful comments.
[+] TheAceOfHearts|6 years ago|reply
Sometimes you encounter some questionable code and you wonder: "What idiot wrote this?" So you `git blame` and you find out "Oh, I'm that idiot."
[+] philwelch|6 years ago|reply
> Learned as junior: New tech solves old problems.

> Understood as senior: New tech creates new problems.

Yep! When you use "new tech", you're making a bet, and not all bets pay off. If you're cautious, you'll hold off until new tech is proven (or pilot it cautiously before migrating). If you're possessed with good judgment, you'll be discriminating in which new techs you adopt. If you have both virtues, you may even gain a competitive advantage.

[+] whatever_dude|6 years ago|reply
> Understood as senior: Communication skills matter most.

I've been of a similar opinion at some point, but now that I see people _optimizing for communication_ as juniors in lieu of actual technical skills, I say: both matter a ton. I hate dealing with a junior that is an extremely good people person but a terrible developer: they tend to think they got everything covered just because people like them so much, even when their actual solutions are terrible.

[+] SkyMarshal|6 years ago|reply
>Learned as junior: Technical skills matter most.

>Understood as senior: Communication skills matter most.

I see this often, but it needs to be said with a caveat - the second line presupposes the first. Without the first, the second doesn't really matter (or it does but you're in the wrong career).

[+] bpyne|6 years ago|reply
"Understood as senior: Legacy code that I wrote myself is hard to read."

Your comment came at the perfect time. I just finished debugging a "high urgency" problem with a program I developed and maintained for the past 10 years.

The program started simple with a small list of rules to apply against data sets. Over time the list became a tree of rules that expanded in both breadth and depth. It was refactored once to get the design in line with the rules of the time.

The "high urgency" issue turned out to be the program working correctly. But, the functional user wasn't able to keep in mind some of the rules he set. It took me a half hour, with lots of "why did I do that", to explain it again to the user.

[+] kbenson|6 years ago|reply
> Understood as senior: Legacy code that I wrote myself is hard to read.

As it should be. If your code from a five to ten years ago doesn't make you cringe at least a little bit, the right way to view that is not that you were doing a good job back then, but that you haven't gotten any better since then.

[+] justbaker|6 years ago|reply
>Understood as senior: Communication skills matter most.

I can't speak enough on this one. In our craft, The better one is at communication skills, the more effective their technical skills will be.

[+] taneq|6 years ago|reply
> Learned as junior: If you report an OS bug or some other deep problem, seniors will not believe you and assume you're making excuses for your own bugs and lack of understanding.

My mum told me "if you think you found a bug in the compiler or OS... you're wrong". This advice applies until you're good enough to know it doesn't. She was right.

[+] JustSomeNobody|6 years ago|reply
> Learned as junior: New tech solves old problems.

> Understood as senior: New tech creates new problems.

This is one all the people who push "new and shiny" need to learn.

[+] jv22222|6 years ago|reply
> Learned as junior: If you report an OS bug or some other deep problem, seniors will not believe you

Same thing happens in reverse! ;)

A few years back I told 3 devs who reported to me that there was a bug in Laravel database sub system.

The bug was: If you use the word "returning" in any Laravel insert query the system would crash (Laravel 3 & 4).

None of my guys would believe me!

I finally tracked the bug down to

> laravel/database/connection.php

> public function query($sql, $bindings = array()) > { > ... etc ... > elseif (stripos($sql, 'insert') === 0 and stripos($sql, 'returning') !== false)

I sent an email to the Laravel team and never got a response... but the bug stopped happening some time after that ;)

I think it was relate to mySQL version as well.

[+] taneq|6 years ago|reply
The big one for me was the realisation that the code doesn't matter. I mean sure, it does, to us. It's what we do. But really, code doesn't matter.

To the end user, what matters is that we solve their problem. We let them do their job, and we make that job as easy as possible. And that's what they pay us for.

And to the company we work for, what matters is that we solve the end user's problem, and that we do so in an expedient and economical manner, so that it costs less for us to do so than the customer pays us.

Of course, for us to continue doing this, in the long term, we need to innovate and architect and uphold standards and stay on top of technical debt. And all of that put together is "make the code good". But that's an end to the means, and the customer doesn't care what horrors awake when they click that dialog box button as long as the result they needed pops out at the end.

[+] docker_up|6 years ago|reply
Overall a good article, but I completely disagree with the notion that "good enough is good enough".

I've been in a lot of code reviews where developers push back because it's "good enough". You need to maintain a defined level of quality otherwise codebases go to shit very, very fast.

I was recently told in a code review that a Cassandra read before a write (to ensure there were no duplicates) was "good enough" because a duplicate "probably wouldn't happen very often". Meanwhile, the consequences of a dupe would lead to a pretty bad customer experience.

I pushed back hard and forced the developer to rewrite his entire code. Would "good enough" be okay in this situation? My bar is much higher than this developer and I stand by my decision. We have the luxury of being tasked with solving customer problems and if we only strive for "good enough" every time instead of "the best I can do within the constraints I'm given", then in my opinion your career won't be very successful. We always have to make the best tradeoffs when it comes to time and expense, but the best developers are the ones that come up with the best solution and the best code that fits in a particular constraint.

[+] AdmiralAsshat|6 years ago|reply
> So imagine my surprise when I showed up at my first day on the job at a startup and found no tests at all. No tests in the frontend. No tests in the backend. Just, no tests.

That one hits home. I felt like I was being so helpful when I, fresh-eyed after finishing some entry-level C language book, suggested that we should implement unit tests to the legacy software.

The product lead, to his credit, did not chew me out, but stated very reasonably, "This software is old, relatively stable, and will likely be dead or sunset in five years. It's not worth the man-hours it would take to try retrofitting unit tests onto a piece of software this old, only for the product to be killed six months after we finish writing them."

[+] mevile|6 years ago|reply
Tests are a really important part of development. There's nothing wrong with suggesting tests. The wrong thing is to insist on it to the point it creates a conflict with you and your team. Either set an example and write tests and see if it creates value and your team is OK with it, make a convincing argument or if you think tests are needed very badly because everything is broken all the time and you can't convince anyone, get a new job. Sticking around and being bitter about it is the thing that's bad.

I usually ask upfront in an interview if the team writes tests and if they don't and I get the idea they don't want to I probably wouldn't work there.

[+] asheikh|6 years ago|reply
My Absolute truth I unlearned as a Senior developer. your knowledge, hard work and quality of work is not important. The relationship that you have with your boss and your bank account is what you need to focus on.
[+] hiram112|6 years ago|reply
> your knowledge, hard work and quality of work is not important.

Bingo. I used to be that guy who'd spend my weekends fixing the code that everyone else left messed up on Friday or at the bookstore reading up on the latest framework. And I thought that someday it would be recognized with promotions or more pay or even a pat on the back.

Nope.

> The relationship that you have with your boss ...

I should have been the guy who was always socializing with management at the office and happy hours. I should have been pushing my way into positions that were closer to the money itself - like getting contracts, attending conferences with management, architecture etc.

This is becoming even more apparent as I hit middle age, and it's harder to justify my high salary when the majority of our code isn't really all that complicated.

> and your bank account is what you need to focus on

But deep down I always knew this was true, so I lived frugally and saved most of my money. I honestly don't see a great future for guys like me who enjoy programming but are too introverted or just don't care to go into management positions. There is simply too many H1Bs, foreign competition, etc to justify high paid developers in most companies that aren't doing Google type development.

[+] bradlys|6 years ago|reply
This is something I've noticed early on even as a junior engineer (maybe it's my general upbringing that highlighted this well known fact of life). It becomes obvious quite quickly how little your knowledge and work matters. You can be incredibly smart and come up with wonderful solutions but it won't mean a thing if your boss(es) doesn't like you.

For a profession that has frequently professed meritocracy - it is certainly not. It's unfortunate.

[+] colechristensen|6 years ago|reply
You need to focus on all, not to switch between one and the other.

It doesn't matter if your work is amazing if nobody realizes it (unless you are fine being a starving artist, no judgement)

The corollary isn't that you should make everyone think your inadequate work is amazing. I don't think you personally are making that judgement but there are people who would.

[+] redleggedfrog|6 years ago|reply
What a great article.

Definitely goes under the heading of "Truths So True They Seem Obvious."

As for "Disorganized or messy code isn’t the same as technical debt," I can't look at messy code without automatically cleaning it up. It's automatic as I read and understand. In the last 5 years I've probably checked in hundreds of PR's of cleanup. If this takes anymore time and/or effort on my part I don't notice it. The only thing is someone has to merge it.

[+] hashhar|6 years ago|reply
I have a rule of thumb to assist with this. If i feel like I have to maintain some state in my mind to understand a particular piece of code then I opt to clean it up since it'll potentially save future developers that time.
[+] yxhuvud|6 years ago|reply
There is the debt that is localized to a singular place, and there is the debt that is all over the place and that is a death by a thousand cuts. The former is easier to fix (and will probably be fixed by some enterprising person, but then second one is the more nefarious one that a lot fewer people actually take the time to do anything about.
[+] jeremycw|6 years ago|reply
As a Junior: Creating the most abstract grand architecture to apply to every facet of my application will solve all my problems.

As a Senior: Replacing all this architecture astronaut indirection with simple linear concrete code will solve all my problems.

[+] edw519|6 years ago|reply
Excellent article! Thank you, Monica. You just put into words a whole bunch of stuff that I always "sensed" but never "said".

After spending 7 million years (it sure seems like it) cleaning up the most vile garbage code you could possibly imagine, I'd like to elaborate on this:

Architecture is more important than nitpicking. While a small line of code could be improved, the stuff that tends to cause bigger problems down the line are usually architectural. I should’ve focused more on the structure of the application than tiny bits of code early on.

Architecture = the sum of all those seemingly unimportant "tiny bits of code".

It seems like every time I have to refactor or (heaven forbid) rewrite, I have to start deep down in those tiny bits. I've worked places with all these "genius" architects, but when I dive deep down into the code, I find a sewer than couldn't possibly support software life as we know it, no matter how brilliantly it was conceived.

Fellow programmers, you probably know exactly what I'm talking about, all those cancerous tiny bits that kill even the strongest patients:

  - variables so horribly named that no one could ever interpret them
  - 800 line iterations surely destined to be broken by a maintenance programmer
  - conditionals so illogical that no one can tell if they ever worked
  - early exits to hell that can only be fixed by rewriting
  - double negative logic that could not never fail to break
  - 8 lines of code where 1 could do
  - <add your own>
Great architecture comes from both directions, "above" and "below". From my experience (unlearned as a junior developer :-) ), 90% of the problems have always seemed to come from below.

Get good at the trees and the forest will flourish.

[+] chrshawkes|6 years ago|reply
From my experience of working at Fortune 100's for over 10 years as a senior engineer, I would say I have seen what you described, but rarely if ever are they the architects fault. There are usually just a few of them and usually hundreds of developers constantly shoveling garbage into the codebase. They rely upon processes and such... but they all fall apart in practice.

I've come to the conclusion good is good enough and working is even better. Usually the business agrees.

[+] reymus|6 years ago|reply
> - early exits to hell that can only be fixed by rewriting What do you mean by that?
[+] alexhutcheson|6 years ago|reply
Multiple of these points could be grouped under the general belief that "Everything is equally important". The #1 change required for growing into a senior role is to form a habit of ruthless prioritization of how you spend your time (and your team's time, if applicable).

Often you end up in situations where all of the following are true:

1. Your teammate or colleague is designing or implementing something.

2. You have different ideas about how that thing should be done.

3. Your ideas would produce an objectively better system.

4. Even though (3) is true, the improvement to the system or design isn't worth the cost in your time, team velocity, team morale/development, etc.

In that case, the right move is not to intervene, and to let your teammate design/implement the system their way. This is hard to do, because most engineers are natural maximizers[1], but for most tasks you're much better off with a satisficing[2] approach. This isn't to say that you should never give feedback on designs or in code reviews - you absolutely should, but always remember that you have a limited budget for your own time and for team morale, and you should spend that budget on the feedback where it will make the biggest difference.

[1] https://en.wikipedia.org/wiki/Maximization_(psychology)

[2] https://en.wikipedia.org/wiki/Satisficing

[+] arvinsim|6 years ago|reply
> I also learned that job titles don’t “make” you anything. It’s kind of like, being a CTO with a 5-person team is different than with a 50-person team or a 500-person team. The job and skills required are totally different, even if the title is identical. So just because I had a “senior” job title did not make me a senior engineer at all. Furthermore, hierarchical titles are inherently flawed, and difficult to compare cross-company. I learned it’s important not to fixate on titles, or use them as a form of external validation.

Unfortunately, they do matter in the real world.

[+] duxup|6 years ago|reply
They certainly "matter" but I think the point more is that skills, responsibilities, ability from one place to the next with the same title is not a good comparison.
[+] taneq|6 years ago|reply
True, but the realisation above is key to understanding how career progression works once you hit your cap. A developer can become a senior developer and then a technical lead and then... what? A manager? You can't really go past technical lead while still staying in the trenches.

So what you need to do is be the tech lead for a team working on a bigger problem. Your job title doesn't have to change as long as you're working on a bigger job.

[+] dullgiulio|6 years ago|reply
Well, depends. I know people going from CTO of a small start-up to individual contributor in a bigger company, probably for money.

Titles count a lot inside an organisation, thought.

[+] iamleppert|6 years ago|reply
> "Good enough is good enough"

+1000 to this. Please don't be the guy that slows me down and prevents me from delivering features because you insist on everything being perfect. I can't tell you how many times and how much money people who are obsessed with code quality waste. They spend months polishing code only to get out a feature that no one uses and doesn't matter. But hey, the code is "perfect"!

[+] SamuelAdams|6 years ago|reply
> Documentation lies

This is a very true statement, especially concerning legacy codebases. I have worked on some projects that have had several developers make changes to it.

The original developers were great: they commented every class, had comments for all the methods, and added comments for any complex or funky logic.

Then the changes came. And the next developers hacked and slashed the existing code base to meet the new spec. Except they did not update any of the comments, so now what was once true and reliable is now frail and questionable.

Now, whenever I inherit legacy code riddled with comments, the first thing I do is delete all the comments. This helps me focus on what the code is actually doing, rather than what someone thrice-removed said it should be doing.

[+] cuddlecake|6 years ago|reply
I was thinking about this and because of the book _Clean Code_ I had already decided that comments will lie at some point.

So I moved towards descriptive variable and function names, but those could lie as well.

So I'm thinking, how could we ensure truthful intentions at all?

And I think only a combination of small pull requests, good variable and function names and a thorough review can save us here.

But I don't know, I'm just a junior developer.

[+] randyrand|6 years ago|reply
Variable names can also go stale - you should consider replacing all the variable names with placeholders. /s

Deleting all the comments is too far in the extreme. How about just read them and realize they could be stale?

[+] harel|6 years ago|reply
I've been programming professionally for well over 20 years (and many years prior as a hobby), and held "senior" to "C-level" positions. in my eyes I'm still a junior kid learning new stuff all the time. When I stop seeing myself as that, I'll switch vocation.
[+] lukejduncan|6 years ago|reply
"Loads of companies and startups have little or no tests" which should scare you, or at least it would scare me if I joined a team.

You can definitely over test, but how can you possibly know what you built works (or still works when you change it for the 50th time) if you have no tests? There's a trade-off with testing. Early in the dev cycle, not testing can make you go super fast (supposedly, this hasn't been my personal experience but in general it seems to be true for teams). But you'll plateau quickly and then at iteration 1+n you'll just come to a screeching halt because you introduce bugs or the new engineer isn't confident that they didn't break downstream things and needs to manually test everything. Testing early will cause you to go slower earlier (again, not my personal experience but seems to be generally true of teams) but you'll be significantly faster at iteration 1+n.

I usually summarize this as: testing early will on average make your development faster over the life of your codebase. Knowing this you can make trade-offs. Not testing early is probably better called prototyping. It's OK to prototype in production if you need to. But know what you're getting yourself into.

[+] tombert|6 years ago|reply
About two years ago, I didn't get a promotion to "senior engineer" that I thought I was going to, and I had a huge temper-tantrum to my boss about it as a result (I'm still surprised to this day that I didn't quit on the spot, to be honest).

I was upset, because people that seemed to be contributing less and were less-qualified (at least from my admittedly-biased perspective at the time) were promoted to a higher level than me, and I got a fairly form-letter-esque answer of "we don't have the budget to promote you this time".

The next cycle, they corrected it, and I was officially a "senior engineer" on paper, and I realized how silly my hissy-fit had been. Sure, I guess having a bit more money was nice, but it's not like it radically changed the quality of my life, it's not like having a fancy title changed how people really saw me, and I didn't even bother updating the title on LinkedIn.

I don't think I was "wrong" in what I said. I do think that I deserved the promotion over someone else, but at the same time, I also tarnished a relationship with my boss and coworkers, and I let it get me far more depressed than it should have.

-------

I guess if any "junior" engineers are reading this, try and remember that a title is simply that: a title. They don't matter a lot, try to not get too upset over them, and obsessing over something so nominal is a great way to build up anxiety.

EDIT: Just a note, I absolutely think you should call out a company if you feel like you're being taken for granted. I'm not advocating complacency, just make sure that your hatred is directed to the right places and try to avoid getting too depressed.

[+] exabrial|6 years ago|reply
The #1 absolute truth I unlearned was: The solution to your problem is the tech stack or framework you're not using. Everyone in this industry seems to have tech wanderlust; using the latest and greatest and unproven is seen as sexy.

* "Oh we could do that, but we're on python 2.7"

* "Oh we could do that, but we're using Java"

* "Oh we could do that, but we're using a relational database"

[+] jasonlhy|6 years ago|reply
1. Code and communication are the most important. If you are writing extremely bad code, you will be annoyed how much time you will need to go though to find the bug. The more you do, the more you will not like to touch the code even they are written by you. (I have seen someone with this experience) Understanding what your teammates are doing is also important in order to support each other and provide valued advices, in this case code is a communication medium.

2. To write good software, we cannot just be a coder, we need to understand the business and the project management

3. There are many seniors became senior because of their age not their ability. I am not talking about using a particular tech, I am talking about their mind. Many of them still think like junior even they are at a senior position, the way they are working didn’t scale at all.

4. Fundamentals is very important. https://hackernoon.com/the-doctor-and-the-scalpel-78656f508c...

[+] jmull|6 years ago|reply
Great post. Lot's of good stuff.

Just to comment on one part at random:

Code reviews would be more useful if review feedback was categorized:

1. is this a matter of personal style? 2. is this a judgement call? 3. is this something that is just wrong and has to be fixed? 4. is this in-scope or actually a separate issue?

(This is off the top of my head, so this is more of an example of the kind of categorization I'm talking about than a proposal.)

It's useful because it helps to set the direction and expectations on what to do about an item of feedback.

E.g. if you have a lot of 1. then the right "fix" might be to spin off a task to develop a common style-guide. (Or maybe fix an out-of-date a style guide, or to enforce an existing style-guide so that these issues don't dominate code reviews, etc.). For 4. the resolution would be to open a ticket (or whatever the process is so it gets proper consideration, prioritization, etc.)

Where I am currently we spend a lot of effort figuring out what to do about review feedback (and I think we too often make non-optimal decisions which sucks time as well).

[+] jasonhansel|6 years ago|reply
I think another truth to unlearn is "users know what they want, and can express what they want in precise technical terms."
[+] scriptkiddy|6 years ago|reply
I don't know if I can call myself a senior. (none of the companies I've worked for have used senior/junior in their job titles), but one of the most important pieces of information I've picked up is this:

The Simplest way is usually the right way.

What I mean is that fancy algorithms, sweeping design patterns, and "clever" pieces of code are generally not the best approach to 99% of coding specific problems.

Example: Nested for-loops. Generally a bad choice. When encountering a nested for-loop, one may be tempted to try and refactor it into some sort of recursive and highly-performant function with O(n) complexity, etc. You go through all that work and then realize that the most iterations that for loop will ever see is ~10. You just wasted a ton of time writing code that is more complex, harder to debug, and generally more opaque.

In my experience, I've seen this a lot in the context of premature optimization. I've also been the perpetrator many times as well.