Improve your development ROI đ with a lean approach
What is lean? đ¤
Generally speaking, when we talk about lean in product engineering, we're often looking at it from a team or organisation level.
We try to eliminate waste in the software delivery lifecycle by doing things like:
- using agile methodologies
- using DevOps principles to reduce hand-offs and bottlenecks etc
- removing red-tape
- improving communication and shared learning
For some organisations these changes require a fair amount of restructuring and with that comes risk and a cost.
While these are great principles to follow, they arenât the focus of this article. This article will focus on optimising engineering at a low level with no risk and instant gains.
What is lean engineering? âď¸
Lean engineering is all about removing waste and unnecessary processes from engineering.
It mainly involves being pragmatic rather than dogmatic, and following best practices when they add value, not just to tick a box.
Sometimes an engineering practice does add value, but it takes a lot of effort, and in fact, it might not be worth it or there might be a cheaper alternative.
Later in the article, weâll see some techniques to optimise an engineerâs day-to-day workload, by:
- assessing the return on investment of software engineering practices
- removing any practices that arenât worth the effort
- finding cheaper alternatives that increase the ROI
Common mistakes đ
One of the biggest mistakes Iâve seen is when a team decides to add a quantitative measure of a best practice and set some arbitrary threshold.
These quantitative measures arenât an indication of value. All they do is distract an engineer with a box-ticking exercise.
âEvery function should have a commentâ
Iâve seen examples of this where engineers have written doc blocks that just repeat the function and parameter names to âtick the boxâ.
...
/**
* Check whether a number is even
* @Param number the number to check
* @return returns true if number is even, false otherwise
*/
function isEven(number) {
return number % 2 == 0
}
...
When the majority of functions have this sort of doc block, it means that all engineers just stop reading them, so by the time they get to a function that could use some explanation theyâve gone comment blind.
Whatâs the return on investment here? The engineers have wasted time adding pointless doc blocks, the reviewers have had to skim read through those pointless doc blocks, and then itâs made any future engineers blind to comments altogether. Hours could have been wasted each week here and thereâs little or no value to be gained.
An alternative is to ensure the code is clean and easy to understand and doesnât require explanation.
âAll pull requests must have 100% unit test coverageâ
Iâve seen this all too many times too. Iâve seen tests where the developer has made sure the code gets executed but no actual checks are done. This tricks the code analysis tools and shows up as 100% unit test coverage.
...
describe('Test the thing', () => {
callAllTheCode();
expect(true).toBe(true);
});
...
With unit testing, the return on investment varies by scenario.
In many cases, unit tests donât cost very much to write and offer both short and long-term value. They can give the author immediate feedback that their code is working as expected without the need to deploy the code to an environment and run manual tests against it. Future engineers can then use those same tests to: help them understand the functionality ensure they donât make a breaking change to the code.
Some unit tests offer very little value and often theyâre the ones that take the most effort to write. For example, the code that handles an API request, letâs assume that the unit of code calls three other functions:
- one to validate the request
- one to transform the data
- one to write a record to the database
Chances are:
- youâve unit tested your validation function with a whole bunch of different scenarios
- youâve unit tested your transformation function with a whole bunch of scenarios
So to unit test your API entry point, youâve got to mock out three functions and then just check that theyâve all been called with the correct values. This test wonât give you many short-term gains as youâve already unit tested a bunch of different scenarios with the validation and transformation logic, and the tests wonât offer much value to future developers because chances are any code refactors in this function will likely require the tests to be updated too.
In this example, you should probably cover this entry point with a couple of integration test scenarios which should offer more value than the unit test and would likely be less effort, and when combined with the unit test scenarios youâll have pretty decent coverage.
Return on investment assessment đ°
One technique you can use with your engineering team is to look at the various practices your engineers follow and attempt to measure the value they add versus the cost of doing them.
Many experienced engineers will make these assessments automatically as part of their process, but it can often lead to conflicts with more dogmatic or less experienced engineers who care more about ticking the box than adding the value.
In most environments, itâs best to âmake it officialâ and do this assessment as a team so that everyone has a shared understanding and an opportunity to learn from each other.
Assemble your team
Get your engineers together, either physically or virtually around a whiteboard. Youâll likely need at least an hour for the session and to make things run smoothly itâs worth getting your engineers to start thinking about best practices ahead of the meeting.
Itâs also worth setting an expectation based on what youâre working on. If it is just a proof of concept or a prototype you can probably throw out most of your best practices and just focus on rapid releases.
List your engineering practices
Allow some time for your engineers to collaborate on a list of engineering practices, these practices can be things that the team is or is not currently doing, and it doesnât matter whether the engineers understand the value of the practice at this point.
You can do this by either nominating a scribe and calling out answers or getting your engineers to put sticky notes on the board.
At this point try to keep discussions to a minimum. No answer is right or wrong at this point.
Make a shortlist? đ
The next step is to quickly eliminate practices from the list, if at this stage no one can see the value then just eliminate it.
Quickly work through the list and just check that at least one person understands the value of the practice. If someone sees the value, leave it there and move on, if no one sees the value just eliminate it.
At this point, you might end up breaking down or caveating a practice because thereâs value in doing it in some scenarios but not others. Think about our unit testing example above, it might be that no one on the team sees value in unit testing a controller, but everyone sees value in unit testing X, Y, and Z.
Assess the return on investment âď¸
The next step is to work through the list, let the team have a quick discussion about the value the practice adds, and make sure everyone has a shared understanding of the value. Consider what the alternatives are (and whether those alternatives are already on the list).
Look out for comments like âwe do X in case Y happens in the futureâ. If Y never happens then does doing X add any value? Perhaps X should be done at the same time as Y.
If the team decides there is some value then we need to estimate the return on investment. Thereâs no hard and fast rule here and you might need to mix and match techniques depending on the practice.
Higher or lower
The simplest way to get a feel for the ROI is to get your team to vote on whether they think the added value is worth the effort.
If the results are fairly unanimous then job done, if not then you can either discuss it further or try delving a bit deeper into the quantitative measures.
Quantitative measures
Try to estimate the cost of following the practice and the cost of not following the practice. They donât necessarily need to be the same unit. If they are the same unit, then itâs a nice and simple calculation. If not, itâs up to the team to use the estimates to make a call.
Writing integration tests takes 10% of the teamâs time per week (developing, reviewing, waiting for builds, etc). Over a two-week sprint for five people (5 people x 8 hours x 10 days) thatâs 40 hours per sprint.
On average the integration tests catch one issue per sprint.
At this point, the team can work out whether itâs worth 40 hours per sprint to catch that one issue, or would they be comfortable having that one issue make its way into production and having an extra 40 hours each sprint.
Once youâve done this exercise the quantitative data can be quite useful to help drive the technical roadmap, and potentially decide to use an alternative approach. For example, you might decide it is worth investing 40 hours a sprint into dark releases or improvements to monitoring rather than integration testing.
In summary
Eliminating box-ticking exercises, maximising time spent adding real value and trusting your engineers to make the right call will not only optimise your development output but will also improve outcomes and make your engineers happy bunnies.