Escape the trap of “House of cards”
In an era that lives and businesses depend on programmers’ work more than ever, yet more glory seemingly lies in being a hacker than a professional. How can startups and high-growth IT companies prevent the products turning into a “card tower”?
Rethink the badge of professionalism
I learned to write clean code in school, then the reality hit. The requirements keep changing, management pushes aggressive deadlines, people modify code before understanding it … it ends up ugly. Things will be better next time.
Management ignored my expert opinion. It wasn’t my decision to make.
— The engineer
Uncle Bob told a story in his book, The Clean Coder: A Code of Conduct for Professional Programmers. Before the Space Shuttle Challenger disaster, engineers knew the risk was too high. They wrote reports, designed a repair and protested again in a meeting hours before the launch. The managers ignored them.
Why does management seem to respect the advice from HR and Legal professionals, but often overrules engineer’s estimate and opinions? The badge of professional respect comes with great responsibility and accountability. The professionals communicate with clarity and confidence. They call out the consequences of each decision. They take responsibility for their professional advice.
As an engineer, if you made a mistake and costed the company $10K, are you prepared to write a check or do you expect the employer to pick up the tab?
If you don’t feel ultimately responsible for your own mistakes, how can you stand up for your opinion? An engineer has a depth of knowledge that no managers can possibly have, with which comes the responsibility to act. A suggestion with clear tradeoff analysis and an actionable plan is more likely for others to act upon.
When management feels that they can not determine the severity or impact based on the engineer’s words, which happens rather frequently because not all engineers are specialized in communication, rather than dismissing it as “crying wolf”, they need to find a way to get more measurable information from the engineers.
Speak truth to power
Management asks to deliver under half of the engineer’s estimated time to meet customer’s deadline. The senior staff prescribes a solution the engineer knows to be faulty. The engineer says,
His answer is taken as an agreement. And he thinks “when it fails, it’s not my fault”. The employer will likely be one to deal with the consequences.
Is he being a team player by maintaining harmony during conversations, or instead by helping management to find the proper goal for the team? Is he truly identified with his employer and treat their problems as his own?
Do or do not, there’s no try. — Yoda
Half-hearted attempts are harmful. What can someone do differently now that he is “trying”? Has he been holding back reserves or was he unconfident of his estimate? Perhaps he said yes due to the temptation to be a hero, and was tempted to cut corners to save face?
Failing to call out risks or ask for necessary help is unprofessional. Watch out for signs of non commitment. A real commitment typically sounds like “I will <do something> by <a certain date>”. Unfiltered debates and full commitment are essential to genuine teamwork. Artificial harmony is dysfunctional and utterly unprofessional.
Get to the right yes by being unafraid to say no, especially when the stake is the highest. A professional is not passive-aggressive, he either raises red flag and disagrees, or commits and engages. Yet avoid too much detail which can be an invitation for micro-management, the why is less important than the fact.
People in different roles often seem to speak completely different languages even when they are face to face. Language barriers between the stakeholders, PM and engineers can cause major discrepancies to slip into late development cycle, thus wasting time and resource.
Two communication traps
- Watch out for the trap of Premature Precision. Customers often don’t have a clear vision of the feature until having actual contact with it. The more precise you make the requirements early on, the less relevant they become at the time of implementation. Only flesh out a requirement when about to implement; iterate timely to validate and get feedback, be open to revisit the design during iterations if you intend to build a top-notch product.
- Late Ambiguity is equally harmful. Stakeholders often disagree. They will find a way of phrasing the requirement that they can agree with, without actually resolving the dispute. Sometimes they hope the readers would know what they mean. Engineers who are tasked with the actual implementation often end up taking on the task of disambiguation, if no one else has.
A perhaps overly simplified example from Uncle Bob’s book:
PM requests for backing up data each night. The engineer asks a technical question: What should the name of the backup directory be, can I call it “nightly_backup”? PM feels it’s a technical detail and has no objection. After the feature is done, it’s rejected because the backup is only kept for one night and overridden by the next run, but the customers need to keep each nightly backup forever.
It would be convenient to say the PM had the spec wrong or was flip-flop on their statements. However, had the engineer asked the question in a way understood by PM or articulated the business consequences (“Do I need to attach date stamp to the directory name so that the backup won’t be overridden the next day?”), the problem could have been prevented much sooner.
It’s common to put burden of communication on PM or management’s shoulder. However in reality engineers and sometimes QA engineers are often better equipped to identify and call out risks and discrepancies, thus more critical for clear communication.
Stay out of the “House of cards”
The only thing worse than not knowing why the product is broken is not knowing why the product works.
It’s working now. Nobody touch it!
When QA finds bugs, we’ll fix them.
It’s unprofessional to send code known to be faulty to QA. What code is known to be faulty? Any code you aren’t certain about. — Uncle Bob.
Be aware that Rushing to Complete often leads to Slow to Market. Have you ever tried to rationalize a new definition of “done” to get the team out of a prolonged task? Did it come back to bite?
Bugs are inevitable, but they should be rare. Every time QA or the user finds a bug, the author should be surprised and determined to prevent it from happening again. Bugs are easy to fix, otherwise those are design flaws instead. Being able to sense your errors is the beginning of mastery.
Estimate won’t be 100% accurate, but it can be adjusted along the way and as early as possible. The ability to predict and estimate is invaluable to software development (and in life), and it’s a skill to be learned and improved continually. An estimate is not a single number but a probability distribution. It is to help business manage the risk, not hide the risk until running out of options.
Keep the code measurably clean
Beauty is in the eye of the beholder. Each engineer has her own style and nothing is perfect. How do we measure if the code is sufficiently clean?
Clean code is easy to maintain. Maintainability means the code is flexible to change with minimal regression. It is the structure of the code that allows it to be flexible.
When an engineer makes changes to the code, it should be easier to make future changes than before.
The best way to keep the code clean, is to make frequent changes and random improvements. It is dangerous to allow the software to remain static. Regular exercise is good for your health. The same goes for the software.
The best cure for fear of changes is to have automated tests.
When the ownership of a component passes from one engineer to another and more regressions start to occur, it’s subject to debate whether the first owner wrote hard-to-maintain code or the second owner is less capable. But it won’t be much an issue, if there is sufficient automated test coverage.
The engineers are already working 60 hour a week. I can’t ask them to write more tests. — A seemingly well-intended manager.
Tests are documentation for the work. Tests are guards of team’s honor and professionalism. Tests improve development speed and time to market. You need to stand up for the right to write tests.
Let engineers do their job
Management is doing their job when pushing for project deadline. PM does theirs by making case for the functionalities they want. It’s the engineer’s job to keep the code clean, and to request enough time and resource to do their own job.
It’s the engineer’s job to understand the domain, enough to identify challenges and errors in the spec. It’s irresponsible for engineers to simply code from a spec without understanding how it makes sense to the business.
It’s the engineer’s job to keep their skills sharp and up to date. On job training is necessary but not enough. Musicians can’t just perform without time for practicing, even though they are only paid for the performances.
It’s the engineer’s job to spread the knowledge and mentor juniors. The best way to learn is to teach. Pair programming is a good way to share knowledge.
It’s the engineer’s (and everyone else’s) job to make the team functional. It’s not the engineer’s job to be a hero. Professionals are honest about risks and their own mistakes, and will not bet team success over false hope.
Let engineers do their job and be accountable. If you want to excel the competition and have a lasting product.
If you enjoyed this story, please consider clicking the ♡ button so more people can find it.