You've spent months learning to code and you’ve finally landed your first job. You made it; you put in the hard work and changed your career. Now it’s your first week in the job, you’re staring at your screen, and you don’t understand a thing. You get that sinking feeling: did I not learn the right things? Am I not intelligent enough to do this job? What on earth is a SimpleBeanFactoryAwareAspectInstanceFactory??
Don’t worry: it’s not your fault, and I’m here to help.
I taught myself to code in my early thirties. I went part-time at my job and spent the rest of the time learning programming and computer science; from programming in C and learning about data structures and algorithms, to making my own games in JavaScript for my new portfolio website and blog.
Nine months later I got my first job as a Software Developer. Since then I’ve worked as a Senior Developer for startups and huge companies, I’ve been a Senior Consultant for multinational banks, and I’ve designed distributed systems that scale to millions of users all over the world.
But when I started that first job I was staring at the screen with no idea how to get my work done.
A few weeks later it wasn’t much better, and I seriously considered quitting and going back to my old job. I thought maybe programming wasn’t for me.
I thought I’d learned the right things. I knew how to program in C, I knew about data structures, and I knew how many bits were in an integer. I knew what an object was, and how, say, a Car could inherit from a Vehicle. But there wasn’t any of that here.
I would sit with a pen and paper, trying to work out step by step what the code did. “So that calls that function, then that passes that to the UserController, then the UserController calls the DocumentFactoryImpl to get an XmlDocument, whose functions are in AbstractDocument…” and then after about five levels of abstraction it would fall out of my head and I’d have to start again. All this, just to show a login form on a web page??
The truth is: I still feel exactly the same every time I start a new job, even now. The difference is that I know now that it’s not my fault. The truth is: software is a complete mess.
I still look at a new codebase and have no idea what any of it does. I still can’t trace a path through the codebase to see exactly what it does. Nobody can.
I still have my head in my hands trying to work out what the hell an AbstractSingletonProxyFactoryBean or an AbstractAnnotationConfigDispatcherServletInitializer is.
The only difference between me and you is that I’ve learned ways to cope with it and get things done despite it.
All developers will tell you that complexity is bad and that our job is to reduce it. But the truth is that most of them love complexity.
If you’ve landed in the Java world, or C#, you will meet people who will argue all day long that a AbstractAnnotationConfigDispatcherServletInitializer is simple because it “does exactly what it says”.
Or the guy who comes up with the most ridiculously complex network of classes, with some clever “design pattern” thrown in, just to show how clever they are, when ten lines of procedural code would have been fine. They understand the code - of course, they do, they wrote it - and secretly they love the fact that nobody else understands it and that everyone has to come to them to have it explained to them. It’s their own little kingdom.
There’s complexity in the sheer amount of tools and frameworks you have to use. Someone adds a framework to fix the problems caused by the last framework, and now you have more problems so you add yet another one. This is a huge problem in software development and it happens everywhere.
Our job should be to reduce, not to add. But most developers love to add. It makes them feel clever, it gets new “technologies” on their CV, and it makes them harder to replace.
Your instinct to try to understand everything the code is doing is a good one, but it’s just not realistic.
You’re probably used to writing your own small programs and understanding exactly what it all does. It’s probably the most beautiful code anyone has ever written.
But it’s not realistic in a huge complicated codebase. Over time you will understand more and more of how the codebase works, but for today you just need to get your work done.
I’m not here to advocate Test Driven Development or any other religion, but an understanding of how to write good tests will help you a lot. It’ll help you focus on just the piece of code or functionality that you’re working on, and it’ll reassure you that you haven’t broken any of the tangled mess that is the rest of the codebase.
You should make it a priority to learn your particular test framework. And you should learn to write readable tests that define the behavior of your code. For example, if you’re writing code like this:
class Whatever {
public function doTheThing() {
// does The Thing
}
}
..don’t do what most people do and write a test like this:
class WhateverTests {
void testDoTheThing() {
// ..
}
}
..where the test simply runs through the method and asserts something arbitrary. People doing this tend to be obsessed with “code coverage”, and they simply want a test that “covers” every code path, without ever thinking “What am I actually testing for?”
Instead, do this:
class WhateverTests {
void throwsAnExceptionWhenArgumentIsNull() {}
void returnsZeroWhenListIsEmpty() {}
void returnsSortedListWhenValidListIsPassed() {}
}
Use your tests to define exactly what your code should do.
This follows on from writing good tests. In a messy codebase, it’s very easy to break things. You can’t just spew out code all over it like you can on your own projects. Break your task down into the smallest possible sub-task. Write a failing test for it, then write code that makes your test and all the other tests pass. Do not disturb the beasts that lurk in the codebase. Commit. Move the JIRA ticket. Make a coffee. Today is a good day.
Again, I’m not advocating TDD and I fully agree with all the arguments against it. But our task for today is to survive.
When I reached this point myself, I got cynical and demotivated. “This is all such a mess…if we just wrote a few lines of simple code it’d all be so much better…I could re-do this entire project myself in a few weeks!”
If you’ve reached this stage I have some advice for you: you don’t get to have an opinion on how software should be made until you’ve made something real yourself, with real users, in the real world. I don’t mean a little JavaScript game that you learned as part of a tutorial, I mean something substantial that is out there in the world being used.
When you do that, you’ll realise how hard it is and how long it takes, and that you have to make some compromises if you want to get things done. Add multiple developers with different skills and different opinions, different departments of the business all wanting different things, and you can see how hard it is to keep a lid on that complexity.
You need to learn Object Oriented Programming properly. And Design Patterns. You can’t have an opinion against something if you don’t understand it properly in the first place.
If you want to survive as a Junior Developer you simply have to embrace the craziness. You can’t beat them, so you have to join them.
But always keep in the back of your mind that this is crazy. It’s crazy to have 1000 classes to render some text on a screen. It’s crazy that to deploy your code to the test environment you have to merge three branches, start five Jenkins jobs, manually edit a config file, do the hokey cokey and turn around.
Learn to deal with it for now, but later in your career you should aspire to inject some sanity into things. For now, you just need to survive your first job.
Also published here.
For more posts on surviving your early programming career, follow me on Twitter.