I believe in the value of the fundamentals, but it sometimes seems like I am the only one. I am firmly of the opinion that the key to true mastery and expertise in software development (and in everything else) lies in having a solid grip on the fundamentals, so solid that you don’t really need to think when you apply them. Whenever I trot this opinion out, however, I inevitably find myself in the minority. You see, we – software developers – view ourselves as problem solvers. We don’t really need to have deep knowledge and understanding of anything (and with the amount of tech we’re exposed to on a daily basis it is pretty much impossible anyway). As long as we know that something exists, we can always infer, look-up and work-out everything we need to be able to use it. This attitude is fine, but I believe it is wrong to apply it when it comes to fundamental knowledge, and this is where many people seem to disagree with me – to my constant amazement. Before looking at this further, let us define what fundamental knowledge actually is.

What Are Fundamentals

A couple of years ago I was asked the following question in an interview. Explain how optimistic locking works, in the context of Hibernate. At the time I had done a bit of work with Hibernate, but I was by no means an expert, so I drew a complete blank. What a total FAIL on my part that was, because optimistic locking is not really a Hibernate-centric idea, it is a fundamental concurrency control concept. I should have been able to fire-off an explanation of optimistic locking in general and I would have been 90% of the way there (regarding how it works within Hibernate).

Here is how I like to look at it. There are fundamentals at the macro level and at the micro level. At the macro level (i.e. looking at software development as a whole) there are concepts, algorithms and knowledge that will be applicable no matter the type of work you’re doing or the domain you’re working in. We’re talking things like arrays, hashes, trees, sorting, searching, some graph algorithms, caching, certain object oriented concepts and yes, even things like lazy loading and optimistic locking. There are a few others, but surprisingly not that many. You need to know these things backwards. The implications of using them on small and large data sets, common problems they apply to, limitations and how to overcome them etc. You will be playing with these every day, for the rest of your career; surely you owe it to yourself to understand them as deeply as you possibly can. Yet, most people have at best a working knowledge, which has remained at approximately the same level since university.

At the micro level (i.e. looking at a specific technology, language or library), there will be API details, tools and quirks that you have to internalise fully in order to be truly effective. When I started learning Ruby, I read all sorts of books and blog posts. I found out about various techniques, tools, gems etc. Did any of it make a significant impact on the quality of my code or how fast I was able to write it? Not really, at least not that you would notice, beyond the natural improvements that you would expect from continued usage. Then, at one point, I spent a couple of hours closely looking at the API of the Array class, I don’t remember what my reasons were, but all of a sudden, I noticed myself coding faster and able to maintain a state of flow for longer. You see, I didn’t need to look-up much to do with the Array class any more, I was really surprised at how much of a difference that made (but if you think about how often we use/manipulate arrays, it is not actually that surprising). You know what my advice would be to someone just starting to learn Ruby? Arrays, Hashes, Strings and Files – learn their API’s off by heart as soon as you can, you will find yourself head and shoulders above most other Ruby programmers straight away. That is micro level fundamentals.

A Solid Understanding

What does it mean to internalise something completely? Let’s take martial arts as an example. You can pick up some books and read all of them. You can have someone show you all the moves and can even try some of them out a couple of times. Does that make you an expert martial artist? Not by a long shot, for that you need to practice, and keep practicing until muscle memory kicks in and the moves become second nature to you. You’ve internalised them. More than that, you don’t spend hours practicing complex combinations (not initially anyway), you spend your time working on basic movements, complex moves are made up of basic ones and if you have those down solid, it is a short step to be able to combine the simple moves to perform the more complex (my apologies to any real martial artists if I’ve oversimplified anything).

Yet, in software, most of us are just like that fan-boy amateur martial artist. We bite off a little bit of Ruby, then some Javascript, moving on to C# and coming back for a taste of Rails, then, back in Java land we take-in just enough Spring to get by and only as much Hibernate as we need to list it as a skill on the resume. We jump from technology to technology, wanting to know and be aware of everything (so we don’t fall behind), but all the while, we would probably have been better off practicing our “basic moves”. It doesn’t matter how many object oriented languages you know, if you’re not precisely sure what coupling, cohesion or abstraction means, your code is likely to be equally crappy in all of them. It doesn’t matter how many inversion of control containers you have used, if you don’t know what problem dependency injection is trying to solve, then you’re just another sheep ready to follow the leader off a cliff (it’s true, sheep will actually do that).

There is a difference between really understanding something and learning just enough to get by (i.e. having a working knowledge). It is usually ok to only have a working knowledge of most of the tech you use day-to-day; there is simply no need to have a deep understanding of the hundreds of libraries and technologies you deal with. The reason it is ok though, is because it’s assumed that you will have a solid understanding of the fundamental principles that all this tech is built upon. You don’t need to know the specifics of the Hibernate or ActiveRecord implementation if you understand how lazy loading, or optimistic locking works. If you have MVC down, then whether you’re using Struts or Rails makes no difference, it’s just an implementation detail. Basically, a good rule of thumb is, the more fundamental the concept the more solid your knowledge of it should be. It’s the whole, solid house – solid foundation thing.

I sometimes think that a generalist with really solid fundamentals could pass for an expert almost every time. Have you ever seen someone walk up to a keyboard, start coding and not stop for 10, 15, 20 minutes, no need to refer to anything? Impressive isn’t it? They seem to produce an amazing amount of useful code in a very short period time and when they leave people whisper the word genius. But there is nothing genius about it, just someone who took the time to learn the micro level fundamentals in that particular area – the rest was just practice. You can do the same, get your macro and micro level fundamentals down solid, after that it’s all about strategic practice, but that is a story for another post. To me, all this just makes a whole lot of sense. I would have thought it would make just as much sense to everyone else and yet I constantly find people to disagree with me on this point – it’s really quite puzzling :).

Images by thivierr and antonychammond