When I was younger, I used to play a lot of chess. There is a famous quote from a former world champion in chess, Capablanca: “A good player is always lucky”. I have come to realize that this applies to software development as well.
Now let’s look at what the real meaning of this quote is. If you thought it meant chess is a game of luck, you couldn’t be more wrong. What it truly means is that good players will (sometimes unconsciously) make good moves, placing their pieces on squares where they are more active. For example, placing rooks on open files and pawns on opposite color squares than the remaining bishop are both basic strategies. Following them will eventually lead to more opportunities and perhaps one of the opportunities will lead to victory. When an opportunity like this presents itself and some tactic can be used to win the game, it sometimes feels like luck.
In software development, following certain principles and patterns will keep more opportunities open in the future. An unlucky developer will often feel that it is hard to add new features and that the features do not really fit into the existing legacy. A lucky developer will often realize that there is a very easy way to add the new feature. Part of it is just because the lucky developer was following good principles when he wrote the old code. Many years of experience will also give a good gut feeling on which way to implement certain things.
Less experienced developers often do object oriented programming wrong. Even experienced developers sometimes break SOLID principles and that may lead to various difficulties when the codebase grows. Juniors sometimes get basic inheritance completely wrong and then wonder why they have programmed themselves into a corner. Many juniors do not know when to use composition and when to use inheritance, so they inherit classes just to get access to methods they need. Not only does this become a testing hell due to lack of possibilities to inject dependencies (stubs or mocks), but it will often lead to various problems later.
Let’s look at a completely hypothetical example, one that I was able to quickly come up with. Let’s say that we are building a racing game and have decided to model how the engine accelerates at different speeds; high acceleration at the lower speeds and then slowly decreasing when it gets closer to the top speed. We have a class Engine, with method:
public double getAcceleration(double speed);
Now a junior will start implementing the Car class, which has the properties: coordinates and currentSpeed. Additionally, it has the following methods used to control the car:
public void setGasPedalDown(boolean down);
The runUpdateCycle() method is supposed to run an update cycle of the game, by first getting the acceleration and applying it to the speed (in case gas pedal was down). Then calculating the new coordinates based on the speed and time.
A senior developer will obviously use composition and let engine be a member of Car, and in fact most likely program against an Engine interface in the car class instead of the concrete class. Some juniors would perhaps jump at the opportunity of just changing the Engine class to be the car class and add the missing functionality there. Some junior developers might (although perhaps not that likely) inherit Engine class to get access to the acceleration method. Both of these approaches will of course work fine, but what happens the day when the producer of the game asks for a feature to let the user switch engine?
The senior developer would just implement a setter method, unless the senior developer already had implemented such a method for for dependency injection and unit testing purposes. Now the junior developers will either have to do some refactoring or continue on a path that will require a lot more effort and eventually will lead to bigger problems. The juniors will experience a lot of bad luck.
This idea of luck can probably be applied to many other professions as well. Or why not for all things you we do in our lives. When we have constantly bad luck, perhaps we should ask ourselves: are doing something wrong?