After working on a project for a while with Agile and analyzing why some things went wrong, I came up with the following guidelines for our team. I printed them out and posted it on my cube wall so I would see it multiple times daily. I see these as supplements to or applications of the Agile principles. I don’t think these are unique to our project, so I’ll share them with anyone who can get value from them.
Here is my list:
Do the right thing, even when it takes more time than the easy thing. In the best case, not doing the right thing creates debt. It is better to do a few things well than a lot of things poorly.
Obey the model. Perfectly. Models exist to provide rules of operation. Where rules exist, assumptions get made. When the model is deviated from, even in small amounts, assumptions get broken, unexpected behavior occurs, and complexity ensues. And stuff breaks.
Always keep it simple. Complexity is our #1 enemy. We must be diligently fighting this enemy wherever it silently creeps in. It is much easier to achieve the *-abilities (maintainability, usability, etc.) when the thing is simple. It’s corollary: pre-optimization is the root of all evil. Keep it simple, and then optimize only what the data tells you is actually needed – it’s likely less than you think.
Prioritize. And revisit the priorities. Start with the understanding that you can’t complete everything. Work on the most important things first. Front-load the risky items so you have time to deal with unexpected bad outcomes. Priorities will help you decide what to leave undone, as you will have to leave some things undone. Revisit the priorities periodically to check if they need to be adjusted, especially due to new information.
Work on the right thing at the right time. This is a big one. If we start with the assumption that there will always be more work to do than time allows, we can’t do it all. So pick the right thing that is most important at that moment. And the right thing will vary based on a lot of factors. It varies over time, usually a lot.
The goals should be clear. If they aren’t, ask. I want my team to understand what the high-level goals are, and how the work they do on a daily or hourly basis helps the team to achieve those high-level goals, and why that work is important to the team. If you can’t answer that positively, then either you don’t understand the goals, you don’t understand the task, or you’re working on the wrong thing. It’s totally cool to raise your hand and say “Help me understand the goals.” It shows that you care and that you are a team player. The only stupid question is the one that is not asked.
Make the best customer experience. Don’t trade “what is best for the customer” with “what is easy for us”. Pleasing the customer over the long term is your revenue source.
Think hard. And ask for advice. Challenge yourself to come up with a better plan, even after you’ve come up with a good plan. Benefit from the knowledge and diversity of those around you. There is value in personal interactions. Don’t be a heads-down soloist.
Any task which is more than trivially repeated, especially if accuracy is important, and can be reasonably automated, must be automated. The only way to scale without a huge increase in human resource cost and human errors is to automate. This also frees you up from the mundane to focus on high-value items. In the long run, the investment will not only be worth it, it will be necessary.
Break up the large stories into digestible-size pieces. If the size of the story is too big, you won’t get it done, and it will just keep rolling over iterations. The way to eat an elephant is one bite at a time, properly swallowing between each bite.
Exercise due diligence, but don’t spin your wheels. Before you go to someone to ask them a question, do some homework. But don’t spend so much time doing homework research that you don’t get the job done in a reasonable time. If you get stuck, back up and take a look at it, and if you still can’t figure it out, then go ask for help. Asking for help is totally OK. You would gladly provide help to someone if asked, right? This is a team, not an set of isolated individuals. Instead of brute forcing something, try to work smarter. Be efficient.
Too much communication is better than too little. As developers, we may not be the best communicators. But communication is essential to a team functioning properly, so we can all do the right thing at the right time. The team’s goals is bigger than what any one person can do. When in doubt if you should let someone know about something, always let them know.
Context is everything. If you understand the context, you will naturally choose the right thing. If you don’t understand the context, you’ll be making a decision blindly. In these complex environments, making good decisions is critical. Understand the context.
When it can be done reasonably, write tests to go with your code. I’m not suggesting about going crazy with unit tests, in my experience that’s not what usually breaks. With solid developers, it’s the integration function that cuts across components is the more frequent issue. But those are also generally hard to automate testing for. But if you can automate integration testing, then you can run it frequently and inexpensively, which will yield great payoffs in bug finding and QA cost savings. Scale!
Don’t let “perfect” get in the way of “done”. There absolutely will be times where your code doesn’t need to be perfect. For example, perhaps the primary business goal is speed-to-market, and the product is expected to remain pliable so customer feedback can guide its future direction, and it is understood to not be mission-critical for the customer. So don’t invest time in becoming perfect because the product is expected to change, and you’ll end up changing that code anyway. “Doing the right thing at the right time” can mean that you are building things to be good enough, not perfect. Rules, including the ones here, should always be interpreted with an “as reasonable” clause.
Test your code before you merge it. Have proven confidence that it works instead of expecting QA to catch basic problems. We currently have a dedicated QA team. But don’t get lazy and expect them to catch issues in your code. The QA team finding a problem in your code should be an exception and not the rule. The QA team is generally better at finding edge cases and interesting integration scenarios. But you as the developer should do enough testing of your own code in your development environment before you git commit + push that you have confidence in your code because you saw it actually do the right thing, not because you are arrogant.
Understand the “iron triangle”. For a product that is considered mature and customers have high reliance on working properly (i.e., bank transfer), quality needs to be there. In the iron triangle, the 3 vertexes are resources (including time and people), content, and quality. If you move one vertex, the other two will also need to change. If you choose to increase the quality, it may take more resources and/or less content. In my current position, we generally have flexibility for time, but generally not flexibility for quality. If you have a product where time-to-market is important and shortened, then quality and/or content will also be lessened.
On average, go at a sustainable pace. There will be peaks and valleys in workload, but getting burned out is bad for everyone: the employee, the employer, and the customer. An unsustainable pace for too long will increase technical mistakes and increase technical debt. Push back if an unsustainable peak duration is creating a bubble that will pop – remember the “irrational exuberance” in the stock market crash of 2008?
We are playing the long game. Battles will come and go, but this is about winning the war. Don’t mistake a battle for the war. This means we may need to take some hits in the short term.
Build for elegance and craftsmanship and simplicity. Then it becomes stable, fast, intuitive, etc. In our organization, the goal is to not finish quickly, the goal is to finish at a good place. If you need more than one attempt to finish at a good place, do it. Obviously, if you can finish at a good place quickly, that would be nice, but quick is not the primary goal.
Be totally honest. If there is something not right that is lurking below the surface, bring it to the surface so it can be seen and resolved. Otherwise it may come back and bite us at a bad time as a surprise. If something isn’t right, do or say something. “What are YOU (not someone else) going to do about it?”
Sense and respond. Once you are on a path, consistently look around and see what is going on. And compare that to your decision to originally get on this path, because you may find that at this new point that another path makes more sense because now you have new information. If a change makes sense, then change. As the saying goes, “the first step in getting out of a hole is to put down the shovel”.
Everything that does something for you also does something to you. (I came up with this quote.) That cool third-party library that helps you get something done easier, will also place limitations on you. Or that business partnership that that you outsource to can become a dependency over which you don’t have control. Be careful.
When something is intended for production, get it to be correct before the launch. It gets way more difficult afterwards. Once a customer starts to rely on something, even though it was a temporary hack, it becomes very difficult to pull it back. It will be a better experience for everyone to do it correctly before production.
Don’t accumulate technical debt. Time-slice in debt reduction. If you aren’t making explicit debt payments in each release, you’re probably accumulating debt.
Have a constant sense of urgency. But don’t go so fast that you make mistakes or take shortcuts. Remember the classic horror movie scene where the guy with the chainsaw is very slowly lumbering toward the victim, but the victim is either screaming and holding still, or trying to run away so frantically that they are tripping over themselves and still going to get caught by the slowpoke lumbering murderer? Honestly, if they would just calm down and walk away at a decent pace everything would be fine. Sometimes you need to slow down to go faster.
We’re not paid to know everything, we’re paid to figure things out. It’s not reasonable to expect a developer to know everything. It would certainly be cool if we did, but in today’s complex world that is pragmatically impossible. However, our value as developers is to efficiently figure things out and then translate that understanding into an implemented deliverable.
It is not an admission of failure to ask someone a question, and you will not be looked down upon. I want folks to be committed to the team (not just to themselves), and have empathy for others that is a source of helping. If someone comes to you with a [let’s assume reasonable] question, would you be offended or look down on them? Of course not. So they shouldn’t do the same to you. You can also think about it this way: You are a member of a team. The goal is not only for the individual to succeed, but for the team to succeed. If you have more to do than one person can handle and get overwhelmed, ask for help. Asking for help is not a sign of your weakness or failure, it is a sign of you caring for the success of the team.
That’s my list for now. There probably will be updates as new lessons are learned and articulated.