How to handle code reviews

How to handle code reviews.

One of my Scrum Masters asked me this question:

Can we skip code reviews? It’s too expensive.

The concern was that it was taking too long for a reviewer to get back to the review requester. The Scrum Master then wanted to scrap code reviews so that code could be more quickly tested by the testers, without having to wait for the review.

This was my response:

Hi <name withheld> and all, 

We should ask ourselves what’s the purpose of having code reviews and to work to that purpose. Yes, there is a cost to code reviews, however the value can far exceed the cost! 

Please read and let me know your thoughts: https://smartbear.com/learn/code-review/agile-code-review-process/

There are a few options here for making our code reviews more effective based on what I understand thus far:

1. Just grab someone from the other team to do a code review. 
2. Set up a peer (1 to 1) meeting to do a code review.
3. Batch up code reviews and make it a whole team affair at the end of each day (or some other appropriate timing).

There are many benefits to code reviews:

Short term:

1. Catch bugs early. It’s much cheaper to fix them before release (or when testing) then it is once its out in the field. 
2. Ensure consistency of code. Part of a good code review includes stylistic review for code consistency.
3. Is reflective for the author of the code as they explain it to a reviewer (are we doing that or just tossing code over the wall?). Many times through the process of ‘talking’ about something, we deepen our learning and understanding.

Long term:

1. Disseminates information across persons and teams.
2. Increases individual and team competencies in coding and domain areas. 
3. Provides repeating opportunities to be reflective (see #3) above. 

Think of the code review as a coding retro. Every time we do it, it’s an opportunity to improve. 

Tze

Code reviews when done well is social a social experience, not merely throwing code over the wall and ticking a checkbox.

To manage scope creep, Product Owners must be nightclub bouncers

To manage scope creep, Product Owners must behave like night club bouncers.

Every project suffers from scope creep as it is impossible to identify all the requirements of a project before it ends. The how of managing creep is not to eliminate it, but to manage what’s in an what out. To illustrate managing scope creep in an Agile project, I will use the analogy of a bouncer in a night club.

Be like Mick, nightclub bouncer.

Every nightclub worth going to manages who gets to go in, who gets to sit at the sofas, who gets a table and everyone else fleeting about like butterflies trying to look like that have a place when they don’t. The crowd makes the night club, not the bar, not the drinks or music, but the crowd. The bouncer controls who gets to come in, guys, girls, hipsters, monied and just normal people. Too much of one or the other and the mix is wrong, the club feels wrong and people leave.

Projects are night clubs and scope are clubbers.

Projects are finite. I repeat, projects are finite.

Agile or not, all projects must end. Agile projects end on time, but not all scope will be implemented. Much like a club, the lights must come on eventually (about 2AM in Malaysia). So the goal then is create the best experience and sell the most drinks in that period.

This translates as creating the most value in a fixed amount of time. Scope comes in various forms:

  • Functional: This is what the end user can do with the application (or services or platforms). This is also where most product owners focus their attention.
  • Performance: Any app that worth using will scale and performance matters. Users today are sophisticated and expects apps to be fast, responsive and not waste their time.
  • Security: We put locks on our doors to keep bad people out. Same goes for apps.
  • Other -ilities: These are all the other things which are important from a longetivity point of view, how easy it will be in the future to maintain or extend the code. The amount invested in this area depends the overall company goals. If you’re an early start up, hacking code together to get to MVP while sacrificing future maintainability may make sense. If you’re established and have millions of users, doing this may be detrimental.

Guy drives up in a Ferrari, walks right in to the club.

Stuff happens, that’s just a reality of life. As much as projects are planned out, things will happen. Opportunities surface, features no longer make sense, whatever. Features or scope enters a project because it has value, so we must not discourage but embrace it! But something’s got to give.

(Caveat: Embracing change is not an excuse for poor planning.)

Sorry Billy, you’re just not cool enough to enter.

For every piece of scope that enters, one must leave. While Agile embraces adapting the plan, removing scope is as important as accepting scope. Accepting a piece of scope that has high value results in removing scope that has less value.

This is the key to delivering Agile projects on time.

So the next time you’re faced with the dilemma of scope creep, be the bouncer to your Agile project.

How to Pair Program

How to pair program

Pair programming was introduced in the book eXtreme Programming by Kent Beck . I’ve come across many teams which said it did not work or that it was inefficient. Pair programming is definitely not for everyone and every piece of work, however most teams that I’ve talked to that tried it, didn’t even do it currently.

Pair programming is one of the trickier practices to get right, but if you do, you’ll suffer the following symptoms:

  • Talking and discussing problems as you solve them with someone else. And they’ll be doing the same to you.
  • Accomplishing more in a shorter amount of time.
  • You’ll lose the urge to check email, your phone or going to the pantry.
  • You’ll feel drained at the end of a pairing session.

Contrary to popular myths, pair programming when done right does not reduce productivity. In fact, it could and will increase team productivity and improve code quality.

Programming or software development at it’s core is solving problems with code. Look at pair programming as a way of solving problems with someone else. Much like how we would use a whiteboard to discuss and solve design issues, pair programming is the same, just in front of a computer.

The benefits of pair programming are, but not limited to:

  • Constantly having someone that you can brainstorm with and validate ideas as you have them.
  • The other person serves as an accountability partner to help keep you focused.
  • Two heads are better than one. He or she may know something that you didn’t know and comes in handy.
  • Two pairs of eyes are better than one, this results in better code quality.
  • Create healthier and closer working relationships.
  • You’ll get to learn more about the code, domain and level up your coding skills.

The above is true for both partners in a pair.

How to start pair programming.

Alright, you’re sold and you’d like to give this a go. So how do you start? Follow these steps:

1. Create a pair.

Find someone that you’d like to work with to pair. That person does not have a be a junior / senior person, but rather just somebody else in the team (or even out of it!) that you’d like to solve a problem with.

2. Find a piece of work to pair on.

This could be a user story, a problem, task or spike. This piece of work should have clear outcomes attached to it. For example, to implement behavior in code that satisfies the acceptance criteria of a user story, or to try out a nice piece of technology if it will solve a specific problem. Simple pieces of work may not be appropriate to pair on, though this could be indicative of a code smell.

To quote Martin Fowler:

It's only worth pairing on complex code, rote code yields no advantage.

I think there is a point to this - pairing is about improving design and minimizing mistakes. Rote code that's simple to write yields little opportunities for pairing to make a difference.

Except this: writing boring rote code is a smell. If I'm writing boring repetitive code it's usually a sign that I've missed an important abstraction, one that will drastically reduce the amount of rote code to write. Pairing will help you find that abstraction.

3. Agree to a time box for this pairing session.

Set a time to end the pairing session. This could be anywhere from 1.5 hours to half a day (or more). The human mind can only take so much mentally intense work that it’s good to have breaks in between.

4. Set the goals of this pairing session.

What are the goals for this session? Would it be to implement a feature, work on some refactoring or find options to a problem. Be as clear as you can. Discussion this as a pair will yield insights in to the solutions for the selected problem.

5. At the end of the session, review what was accomplished.

Ideally, there will be outputs from the pairing session, like code that can be checked in.

6. Rinse and repeat.

Take a break, and start over!

Using Value Stream Mapping as a Gap Analysis Tool

Using Value Stream Mapping as a Gap Analysis Tool

Value stream mapping is an extremely powerful tool. As a way of finding gaps in practice or understanding of a process or methodology, I frequently use value stream mapping as a way to tease out information from the team on how they actually work.

Frequently we assume that if we define a process, e.g. in JIRA, Rally or a physical kanban board, that the team will automatically adhere to the process and all will be fine. I find this to be false more than half the time. Some of the reasons why gaps between process and how teams and people actually work could be:

  • The team or team member interprets the process differently.
  • Process drift, where a process may have made sense once upon a time, but no longer makes sense. The team could either follow it blindly or not follow it at all due to practical reasons.
  • There could be an impediment to following the process.
  • Mixed messages, whereby a process is define but someone, like a manager, may tell an engineer to skip a step to save time. An example would be “let’s skip writing unit tests until we deploy and come back later to do it.” If the exception happens often enough, that becomes the real process, regardless of what’s on a board.

To find the truth in how a team actually works, I use value stream maps to provide a way for the teams to express how they actually work. I will frequently observe much of the following as part of doing this exercise:

  • One or more team members may not even understand the current process.
  • Developers and testers don’t actually know what Product Owners do
  • Developers and Product Owners are unaware of the challenges facing testers.
  • Team members don’t even know why they are following parts of the process.
  • Team members who have little or zero visibility in to what happens after code is deployed or packaged and ready to ship.

Using the value stream in this way will uncover the truth in how the team actually works and as a benefit, promotes sharing across team members in to how each person contributes.

How to use the value stream to gaps and impediments.

First, I’ll need to define a couple of concepts.

  • Value: An article or object that can be created that provides benefit to an end-user.
  • Value adding: The amount of value that is increased in the article or object as it is created.
  • Start: This represents the begin state of the creation of the object or article.
  • End: This represents the end state of the article or object and is ready to be delivered or used by a user.
  • Activity: A value adding action.
  • Steps: The process or stage as part of creating the article or object.
  • Impediment: Any barrier or obstacle that prevents or slows down the creation of an article or object.

For this exercise, use post-it notes as they are easy to move around.

1. Define the beginning and end states.

The beginning usually starts with an idea. It could be yours, from an executive, wherever and that idea is to be turned in to something that is usable or sellable. In software, and idea turns in to code and code in to features which are used by users. The end state could be features or outcomes.

2. List out all activities performed by the team to go from start to end.

Have the team list down all the things they do to go from beginning to end. Use one post it per activity.

3. Arrange activities into a sequence.

Activities happen in a sequence. Sort them from beginning to end.

4. Group activities which go together.

Group activities which can happen in parallel together.

5. Name the steps.

Find a name that represents the group of activities. For example, it could be design for design related activities.

6. Identify what happens to go between steps.

Discuss what happens between steps. Identify impediments, hidden or missing work. Identified actions can contribute to a kaizen backlog.

Next Steps

Value stream maps are amazing simple yet powerful. They are able to visualise processes, an exercise to define a team’s definition of done and is a tool to control work-in-progress via WIP limits. In this case, value stream maps are used to find gaps in processes, identify real work from perceived work and as a kaizen tool to identify hidden work and impediments.

What is Technical Debt

What is Technical Debt?

Technical debt is one of those terms that is frequently used but not well understood. Part of my role as an Agile and software development coach is to inculcate better decision making practices. Designing and building software is as much technical as it is creative with a programmer making lots of tiny trade off decisions in the course of a day. It’s usually thought of that technical debt is accrued through big decisions, however most of it is accrued through the little things we do everyday.

So what is technical debt then and what does it look like? What we usually think of as debt may not be debt while debt could be hidden until it rears its ugly head, much like getting that credit card bill at the end of the month. As we get our paychecks, we could pay of the bill in full or pay partial to have some extra cash on hand but be aware that the principal will accrue additional interest.

Ward Cunningham used the metaphor of debt to explain learning through the normal course of solving a problem with code. There are always little things we could do to improve it, like refactoring, extracting code in to a helper method and having sufficient unit test coverage.

Technical debt slows you (or others) down in the future.

Technical debt doesn’t hurt until you have to work with that code again. Debt could slow you down in the following ways:

  • a piece of code that could have been reused if refactored. There are two choices now, refactored, write it again or cut and paste.
  • code that is difficult to understand.
  • code that strikes fear in your heart when you look at it resulting in “I’m not going to touch that” or “I’m going to have to be extra careful to not break it.”

Shortcuts.

While it may seem like a good idea at the time to save some time, shortcuts create longer term threats to the code. As such, just stay away form it and code it properly the first time.

Some examples of shortcuts:

  • God classes / methods.
  • Hard coded configuration values.
  • Magic numbers.
  • Cut and pasting.
  • Using code from Code Project, Stack Overflow, etc without understanding what it does.

Not applying learning in the course of working on the program

The only time we fully understand the problem we’re solving is after we solve it. The same goes with code. Frequently there’s a list of todos after we ship, like some refactoring, or cleaning up code. Unfortunately most times we don’t get to it.

This is another form of technical debt.

By not taking the time to fix these things, the code will slow get more difficult to work with. The three options then become:

  • Don’t ship the code with todos.
  • Schedule time in after the release to complete the todos. This is more than “we’ll get to it someday.” Actually schedule it in and get it done.
  • Don’t do and expect that development velocity will reduce over time.

What is not technical debt?

Having incomplete functionality is not a sign of technical debt. The following is not considered debt as it does not impede the development velocity with the code.

  • Pre-mature optimization.
  • Functional features (eg. automation).
  • Non-functional features (eg. performance, security). Note: Even though its not considered debt in that it doesn’t slow down developing with the code, it will impact quality and reliability.

How to use technical debt?

As we solve the problem through code, there will be items at the end (or even as you’re coding) that you’d think to yourself to go back and fix it.

Here’s some thoughts on how to manage this.

  1. Create technical debt user stories.
  2. Use code static analysis.
  3. Add a TODO to identify shortcuts.
// TODO: Convert this hard coded value to a configuration value. 

var key = "Some config value.";

Compile the list of TODOs before a release and as a team make a decision to release or not. Periodically review this list.

To summarise, code should be easy to work with, with not additional weight or burden. Just like carrying interest on a credit card bill from month to month, that makes it more difficult to completely pay it off. Code is the same, it should be clean, simple and a joy to work with. The only way we can keep it that way is to pay down our debts.

Continuous Integration as an Innovation Engine

Innovation – that’s an increasingly used buzzword in business today. As more companies have become more efficient, through the use of well known operational processes (e.g. TQM, Six Sigma) and the proliferation of IT has enabled more firms to adopt these methods quicker and cheaper; firms find it increasingly hard to be more successful then their peers. Hence, creating innovation is the latest business trend – and that’s a good thing.

Innovation does not mean that a firm has to invent new products. It does not even mean generating radical ideas. Innovation is about bringing together ideas and inventions that are already there, in a manner which solves an existing problem and generates real economic value.

However, innovation also means failure. Most attempts at innovation will fail and how could it not? The act of innovation is to experiment and try new things and not all of them would be success. Therein lies the contradiction: firms say that they want to be innovative, yet fear failure. To be truly innovative, a firm has to build an environment that not only tolerates failure but to encourage it; to remove the stigma of negativity from the acts that fail would embolden the organization to try bigger and ever bolder experiment, with greater payoffs.

In the business of software engineering, there is ever the contending forces of adding new features and making sure nothing breaks. Most of the projects which I have worked on would inevitably reach a point where the rate of new features added would be outstripped by effects to maintain its stability. Tell tale signs that your projects are nearing this stage is having your application described as spaghetti code, cutting and pasting code as to not “break something” and rejecting a feature request, not because it lacks value, but its deemed to be too difficult.

That’s why continuous integration can be your development team’s innovation engine. An application with a mature continuous integration environment would ensure that the code is healthy and the application works as it is expected. The team is allowed to freely innovate, by adding in big features, radically altering its underlying architecture to enable new paths of growth or even just flat out experiment with new technologies and ideas. If an experiment does not pan out, through a string of unfixable broken builds, just roll back and and you’re good.

Continuous integration is able to form the foundations of an innovation engine, however it is just a start. The team must be willing and able to try, fail and try again.

Purpose Driven Companies Are More Successful

A couple of days ago, I had sat through our company’s quarterly all-hands. One point that struck me was the statement that purpose driven companies are more successful in the marketplace. So that does mean that every company should start being purposeful? Any student of Econ 101 are already thought that firms seek to maximize profit. According to behavioral economics, it may not be profit but rather market share, market valuation or personal perks. But bottom line is that every firm has a purpose, not not every firm is equally successful!

Where success comes from is when the purpose is aligned to those of the market, in the case of a retailer – that would be their customers. Econ 101 teaches us that the market would ‘clear’ at equilibrium, that is when the supply and demand curves meet. What it doesn’t explicitly tell us is that firms must provide something that the market wants, is willing and able to buy.

Take the example of the iPhone and Windows Mobile. Windows Mobile has been around for more than a decade yet it had not captured the imagination of the market in the ways of the iPhone. From my very first Windows Mobile phone, it was very clear the natural inclination was to touch the screen with the fingertip! Microsoft did not listen to his customers and had stuck to the stylus. Apple has listed and gave the market what it had expected.

In the end, its a no brainer. For firms to be successful, listen to your customers and give them what they want in a way that is easy to get it.