Keep It Simple, Stupid
An important design principle, Keep It Simple Stupid (KISS), states most systems work best if they are kept simple rather than made complicated. Take communication for instance — greater simplicity usually increases effectiveness. In this case, engineering is no exception to the rule.
From my experience, team miscommunication and misunderstanding are due to the following:
- There are too many buzzwords to keep up with. It’s not easy to communicate complex technology challenges to members of an organization who are unfamiliar with technology.
- Engineers have different perspectives and experiences with approaches to technology problems. The more we can simplify the discussion, the more we can align our team and achieve our goals.
Before raising issues with team members, here are key things to remember:
- Always start by explaining the direct problem
- Propose at least two solutions
- Solicit feedback
- Try drawing or white boarding to better illustrate the problem and solutions
Commit Often, Commit Early
Committing your code means taking full responsibility for how you are writing your implementation. Engineers tend to push their work to a code repository a couple of times per week. Waiting a few days to see how well your code works with the rest of the system could result in more time debugging system failures when they arise.
Committing often gives you the quick feedback you need. It’s important to know if your work affects the system at large. Naturally, this only makes sense if you have a Continuous Integration build process in place.
Committing early allows engineers to simplify their focus. Most importantly, this approach ensures that the smallest unit of work passes.
Specialist Over Generalist
Having a diverse set of skills is beneficial for solving problems. Broad experience gives one the ability to work cross-functionally. There’s no denying the benefits of being a polyglot. We’re just skeptical about those who imagine themselves as best-in-class in every programming language.
Coding is an art; it’s a lifelong journey expressing simple solutions to complicated human behavioral problems.
Before Implementation, Ask Yourself: “Buy or Build?”
It’s very easy and natural to want to build new technology to solve existing problems related to software development. Your team’s main focus should be on building new software for your customer, as well as areas of technology that directly impact revenue.
Before building a new technology, ask yourself these:
- Are there known services that can accomplish our objective?
- Does this service have an SLA, and is it aligned with ours?
- How often do they make enhancements?
- How reliable is this service?
- Can we easily integrate with this service?
Design your Implementation Through Test-Driven Development
We have another name for TDD, Continuous Refactoring. Designing implementation through TDD allows us to receive feedback on whether we are designing our services effectively.
Our Test-Driven Development Objectives:
- Do not accept poor quality deliverables
- Do not accept expensive maintenance
- Intend to keep code simple
- Expeditiously resolve issues by being closer to the problem
Most engineers write code and then release. Tests are either written immediately after code is considered “done” or written at a point when the feature’s code structure has become too complicated. We call this Automated Testing (not to be confused with the general connotation that most test cases are automated).
We’ve noticed that this gives an illusion of shipping faster, but in reality it creates long-term delays, accumulates technical debt, creates system fragility and produces unmaintainable code. This results in morality issues, as well as increased number of defects in the system after it has been released to users. The most devastating and disruptive outcome will be long delays once your team agrees all of the above need to be resolved.
A better approach is to design the smallest implementation through vetted test harnesses and test experimentation. This should occur during the most important time of development, while the implementation is being written.
The outcome is in high confidents in the software. Team members are much happier with what has been done, because not only is it easier to maintain, but the software is more reliable and highly extensible. Most importantly, you just end up feeling proud of the well designed work they’ve achieved.
By setting the right policy, you can almost always tell when an engineer is approaching their implementation through TDD. Our engineering group has the following expectations after submitting a Pull Request:
- Tests illustrate implementation of business logic around exception handling, edge cases and potential risks
- Code implementation should be easily understood and should have minimal code complexity, and duplication
- Git commit history should be easy to follow, and should tell a story of how the feature evolved
Quality Assistance Over Quality Assurance
Quality Assurance should be part of the entire product development process, and not just the tail end. All stakeholders are obligated to think with quality. Waiting until engineers are done with their work is not the right time to start having risk analysis discussions. Also, it seems to be too late when handing over requirement documentation, all to hope that the QA team understands all that is expected.
This is where Quality Assistance comes into play. Testers are responsible for helping developers improve and better understand how to test software effectively. Testers are there to help identify all possible risk factors. These conversations are continuous, and have no means to an end. This process is also working for companies such as Etsy, Atlassian, and Facebook.
Benefits of Quality Assistance:
- Empower engineers to confidently test by providing training, tools, and environments
- Help the team to produce high quality software, efficiently
- Track efficiency of team’s output, and identify where improvements can be made
- Foresee and prevent problems before they arise
There’s a Human on the Other Side of that Feature
Oh, the joy of talking about which message queue service we should use, and whether it should be RabbitMQ or AWS SQS. As a team we can easily go down the rabbit’s hole while discussing whether our Ruby on Railscontroller is actually following Single Responsibility Principle.
As a team, debating on technology and development philosophy can generally derail focus on the real world problem. However, as a team we try to stay disciplined by narrowing focus around the humans that are affected by the system. Having empathy for your users help teams solve problems that are impactful to people, and not computers.
We are selective with participants contributing to decision making around technology and user centric behaviors. It’s not that we don’t want everyone’s opinion. It boils down to having effective discussions, and speaking to user personas in the right context.
When discussing problems/solutions, always ask yourself:
- Who are the affected users?
- Are the users affected negatively/positively?
- What’s the most efficient way to mitigate user experience friction?
When to discuss technology and user centric problem/solutions:
- When deciding technology solution, do research and work with a tech lead and a peer to improve your perspective (2–3 participants)
- When deciding solutions for user centric opportunity, reach out to a group and survey feedback on your perspective (2-n participants)
- Always relate your work to a specific user persona; these are humans using your software
Building a culture should be a very natural process. One should not have to say, “Let’s build a culture”. It should just exist in a non-intrusive way. Groups should have fun and explore shared understanding while working with each other to achieve goals and objectives for the greater good.
My experience tells me that a team cannot function as an individual or as a group without having a solid socially aware culture. Getting a group aligned on a fundamental level becomes the life-line and bond between all team members.