Playing the Russian roulette with your business · the excitement of the randomness
After spending a few months in an ordinary small French software development company, I’m truly amazed at the effort which makes the whole process highly unpredictable and increases the odds of failing at every step.
If working for a well-organized large software development corporation in USA is like driving a new, well-working and carefully checked and GPS-equipped car on a desert highway, working for those small companies is like driving an old, half-broken motorcycle in the middle of Savanna with no map: you will have lots of occasions to be surprised during the trip and can still get at destination, but you may as well get lost and finish your journey as lion’s breakfast.
The following article is a rant, but a rant which, in my opinion, highlights quite well the way things work in some companies.
Doing stuff the wrong way
The hiring process is carefully designed to pick people at random: indeed, hiring only skillful developers would be boring, since their work is more predictable. Beginners, on the other hand, can reinvent the wheel, or can come with some fancy design which corresponds exactly to the abstract factory pattern, but is not called this way, because, after all, it would be boring to find the same patterns with their real names everywhere: guessing which one is which is much more exciting. Moreover, beginners can come with a solution which will never cross the mind of any experienced developer, because no one with a bit of experience will do a such fragile or complicated thing.
When starting the project, the first thing to do is to avoid writing any software requirements, because, frankly, it’s much more enjoyable to just dig in the development process, discover the requirements progressively, and never track them nor write them down: it helps contradictory requirements to flourish, and means that at any moment, the whole project can be tear apart, because it doesn’t respond to a critical requirement which any customer would need.
When writing code, most standards and conventions should be rejected, because, one, nobody cares—it’s much more interesting to spend five minutes trying to guess the particular convention just to discover at the end that there is none, and, two, standards kill creativity, and it is obvious that anyone who have no idea what clean code is would be the best candidate for creative coding.
By the way, the rejection of standards shouldn’t be limited to code. For example, storage of passwords is an excellent ground to show the full arsenal of creative ideas. Like a home-made encryption techniques, because, everyone would agree, using SHA256 is boooring! A custom-made algorithm may be a complete disaster, because the person has no knowledge of cryptography or mathematics whatsoever, but that’s even better: it adds the excitement to know that the application can be hacked, and the passwords stolen.
Take types. Why would you ever use something like a concurrent stack, provided by the framework? Boooring! Take your creativity at the next level and reinvent the wheel from a simple array. Bonus points if it behaves like a hashset, randomly deadlocks on Friday except when it’s raining, and uses a hand-made singleton which is called differently and can create sometimes its second instance if you insist a bit.
In the same way, why would you ever use a GUID? Isn’t it more interesting to invent your own, which appears to have nothing unique, but that only increases its value, since you can never be sure at 100% that a newly generated entity has an ID which is already in use?
I’ve forgotten testing. Wait, what testing? Testing is inherently bad: it is the routine incarnated. Look at those TDD fans: create test, fail it, implement the logic, pass the test. Create, fail, implement, pass. Create, fail, implement, pass. Such a monotonous task! The worst of all is that tests make your code more predictable, and that’s not funny. What’s funny is to push the new version to production and wonder how long would it take to see the first crash.
If, among all testing, there is one type which can be kept, it’s undoubtedly the manual testing: the good old testing done by hand, with no formal checklist, nor list of procedures to follow. This methodology is truly the best one, since it enables to pass the test once, and then fail it the next time because of a slight, barely noticeable difference in the procedure.
The lack of procedures and automation should never skirt the deployment either. Who can imagine the pleasure and the satisfaction you feel when you finish the manual deployment of a web application which requires to hack the database, update it nearly with your bare hands (given that if you wrongly increment, by hand, the schema version, something, somewhere, will fail), then copy-paste some files to the server in order to discover two minutes later that you actually copy-pasted files from server to your local machine, and by the way, it was even a wrong server, then do some voodoo magic, and, at the end, hack the server configuration and discover that all the websites of all your customers went down!
To justify this madness, there is one thing that is mentioned particularly often:
“Our product simply works; we don’t have to care about how it’s done.”
Well, it doesn’t. And no, actually, you should care.
How does it start?
In order to reach the gates of illusionistic creativity and freedom and achieve the excitement of playing Russian roulette, one shouldn’t make too much effort: hiring with your eyes closed and ensuring working conditions which will make cry any motivated developer would do the trick.
What happens is that random hiring process, based on some serious statistical approaches and metrics, like the stupid years of experience or the dumb number of projects done or the silly number of languages learnt, has everything to ensure that you get the least skillful code monkeys in your company. The ones who don’t know how to write code. The ones who have never read any book about software development. The ones who think that more LOC is better than less. The ones who work for money, not because they enjoy what they do.
This gives a solid foundation of incompetent workers who, given enough motivation, would constantly innovate by bringing the crappiest solutions to the most ordinary problems. The risk is that since the hiring process is random, by bad luck, one can hire somebody a bit less… say… creative. Somebody who has read books, learnt stuff, and is a terrifying illustration of standards, boredom, predictability and routine.
Such person can shake the foundations, or even dare to convince others that TDD could have its benefits or that continuous integration may be not so boring, or that PBKDF2 can be used instead of “encode this to Base64, shift all bytes to the right, separate them by pairs, multiply numbers in pairs and concatenate their hexadecimal representation.” Even if such person wouldn’t be able to do all that, she could still write clean, predictable code, or even start to add unit tests to the codebase, or partially automate the deployment process, or, in general, talk too much. So, this person must leave.
In order for such persons to leave, one can create appropriate working conditions. Scoring zero on Joel test is a good start; if it isn’t enough, The Daily WTF is an excellent source of inspiration. Finally, anybody can invent some tricks to convince those persons that this company is not a good place for them. Make changes to the (implicit and never written) requirements in a way that it would demand monotonous work which takes time, and make those changes just a few days before the deadline. Enforce the lack of style guidelines. Enforce stupid rules nobody needs. Make them read duplicate code inside a 1000-LOC function with no comments and a logic written by somebody who was on a roller coaster when writing it. And if they dare to criticize, tell them:
“Our product simply works; we don’t have to care about how it’s done.”
With a predictable pattern—the only predictable pattern out there—of anchoring the unskilled staff and making cry anybody who dare to show any desire to do how successful corporations do, a part of the task is done.
Another part is to maintain a good environment which would cultivate the Culture of Randomness. To do so, metrics are important, because without metrics, there is no way to promote good people—people who actually sustain and boost the fairy creativity and freedom, and protect your company against the Devil of Routine.
Those metrics, one can pick them carefully. It is important to choose well, since a bad metric can encourage skillful developers—thing we want to avoid.
In order to mitigate such risk, one should select only the metrics which are listed in the literature as being completely meaningless, or—even better—simply harmful.
For example, measure the number of lines written by programmers, and reward those who have inflated the code base the most. Make it clear that those who reduce the LOC through refactoring will be fired.
Another example: instead of valuing the results, count the number of hours a programmer spent at work. Make it clear that someone who spends eight hours per day in front of his desk, sleeping half of this time, is much more valuable for your company that someone who can accomplish the same tasks four times as fast, but stays only five hours at the workplace.
Remember: you should never measure anything of a real value. Don’t even dare to measure something like the code coverage. Oh, wait, true, you can’t, since there are no tests in the first place.
Aside direct metrics, peer support is an excellent thing too. For example, simplicity should be discouraged at all costs. Somebody made an effort of creating simple to understand architecture and refactored her code enough to make it understandable at the first glance? Shame on her! Anybody can do such easy thing, right? Try instead to write a 2000-LOC code with thirty goto
s—that’s the hardcore of programmer’s life.
How does it end?
Imagine that you achieved to hire random people to do your software product in a random way, randomly measured using random criteria. You end up with a randomly working product which fills a random market. Given the lack of competition, or the fact that the competitors are embracing randomness in the same way, you randomly succeed and do a damn good amount of money per year. Indeed, everything randomly and magically works, the results are positive, so why would you ever care about how the product is done?
The first reason to care is the fact that your product might grow. New features may be requested by the customers, or you may want to fill neighbor market niches. Step by step, the code base will become bigger, and at the same time crappier, because no one would care about refactoring. It’s pretty easy to work with a small and crappy code base, but working with a large and even crappier one is a different story. Changes will become slower and costlier. Random bugs, arisen from new changes, will become more and more frequent. While you started with a gazelle, you’ll end up with an old, fat elephant that can barely move and spends his time peeing under himself.
When, instead of responding to your customers’ needs and the constantly changing demand, you find yourself cleaning elephants’ pee, this is the first opportunity to see that something can go very wrong. From there, you have two choices: start doing things the old way, with all those standards, best practices, Agile, QA and other manifestations of the Routine, or keep your head down and do the ram in the direction of the Sacred Randomness, by adopting random measures to randomly identified random problems which may even never exist. Staff—the one which creates the solid foundation of creative incompetence—may also come with creatively brain-damaged ideas. For example, you may end up rewriting the product from scratch while using the exact same practices to keep the old good randomness. No need to say that the second choice goes towards the Russian roulette, giving a competitive advantage to any company willing to steal… well, better to say “take” your customers.
The lack of flexibility in the product itself is not the only element which makes the end of the story neither improbable, nor so random.
A company which hired a dream team filled with experts who will create a high-quality software product can afford failing miserably a project, or leading it to a dead end, or do anything which will cause it to become as attracting to the customers as a fat old elephant that can barely move. The reason why the failure is acceptable for such company is that given its potential, those experts will easily come with great ideas and—this is crucial—they will learn from their mistakes and avoid doing the same error again in the new project.
On the other hand, a company which embraces incompetence and the Bellowed Randomness will have much more difficulty to completely reorient itself in order to target a different market, since there would be no one to give outstanding innovative ideas. And even if such reorientation would be possible, the fact that the culture of the company won’t change will give all the odds for a failure in the new market as well.
A few decades ago, IBM was a leader in hardware and software production. Today, my girlfriend doesn’t even know what IBM is, and never heard the name. Despite the impressive move from a leader corporation known by anyone to an entity known only by IT people and businessmen, IBM stays a successful multinational corporation, far from being dead. Why? Simply because IBM hires people who know their job, and do it well, people who know that the Lovely Randomness has no place in IT, people who seek improvement in everything they do, people who have ideas—great ideas. By embracing the industry standards and best practices, and participating in their growth, IBM has small room for failure. They don’t deliver random products with random delays at a random cost.
By doing the opposite of what large successful corporations do, companies dig their grave. They do it with all their energy and wonderful creativity, seeking any opportunity to fail in the most random way, and to fail badly, keeping as little chances as possible to survive the bad times and the good competitor.