20 Bad Excuses for Not Writing Unit Tests

I guess we always find excuses to keep on with our bad habits, don’t we ? Stephen King

  1. I don’t have the time. But you’ll have the time to fix the bugs …
  2. I don’t know how to write tests. No problem, anyone can learn.
  3. I’m sure the code is working now. The competent programmer is fully aware of the limited size of his own skull …
  4. This code is not testable. Learn or refactor.
  5. It’s (UI|DB) code, we don’t test it. Because it never crashes ?
  6. Because I need to refactor first … and I need tests to refactor ! Damn, you’ve fallen into the test deadlock !
  7. It’s multithreaded code, it’s impossible to test. Because it’s fully tederministic ?
  8. The QA department is already testing the code. Is that working well ?
  9. I should not test my own code, I’ll be biased. Start testing other people’s code right now then !
  10. I’m a programmer, not a tester. Professional programmers write tests.

A quote 'Be Stronger Than Your Excuses'

  1. I’m using a REPL, it replaces unit tests. Sure, and you’re running your REPL buffers on the CI ? and keeping your them for the next time someone modifies your code.
  2. My type system is strong enough to replace tests. Does it detect when you use ‘+’ instead of ‘*’ ?
  3. We don’t have the tooling to write unit tests. Get one.
  4. Tests aren’t run automatically anyway. Install a Continuous Integration Server.
  5. I’m domain expert developer, writing tests is not my job. Creating bugs isn’t either !
  6. We’d rather switch to the Blub language first ! You’re right, let’s do neither then !
  7. We don’t test legacy code. Specifically because it is legacy code.
  8. Adding tests for every production code we write is insane ! As shipping untested code is unprofessional.
  9. I find more issues doing manual testing. Exploratory Testing is a valuable testing, even more so on top of automated tests.
  10. Because my teammates don’t run them. Time for a retrospective.

'Just Do It' written on a board

From Apprentice to Master, How to Learn TDD (Test Driven Development)

I started to learn Test Driven Development a long time ago. Since then, even though I’m still not a master, it’s been my most useful programming skill, by far. TDD is the first trick every new programmer should learn. It made my whole career as a developer easier.

I’ve been working as a professional software engineer for more than 15 years, including around 10 years in the trading industry. Only once did I need to work on week ends or late into the night to fix emergency issues. I believe I largely owe this work-life balance to the high test coverage that TDD ensures by design.

TDD also enables safe refactoring. Refactoring enables incremental design which lets you decide late. Deciding late is how you make your customers happy by accepting late changes. Deciding late is how take up-front design easy, and improve your code as you go. Deciding late is how you build trustful and harmonious relationships with the stakeholders of your project.

Finally, writing tests before the code is both easier and more fun. Among compilation errors and never ending customer demands, the recurring green barre tastes like pure candy to the poor programmer !

A long winding road

The TDD Road

Here are the steps I took to learn TDD.

Learn the principles

The principles of Test Driven Development are fairly basic. 5 minutes is enough to know them forever :

  1. Write a failing test
  2. Make it pass by doing the simplest thing possible
  3. Refactor your code while keeping the tests passing
  4. Repeat until your acceptance test is green

TDD newbies might ask a few questions like :

  • Is making the code compile in step 1 or 2 ? Honestly, that does not matter. Write the test as if you had the code, then make it compile, make sure it fails, and continue.
  • How much should I refactor ? It often takes a good amount of experimentation to find your good balance. If you don’t refactor enough, you going to drown in dirty code. If you refactor too much, you’re going to waste your time (YAGNI). As a rule of thumb, Kent Beck’s rules on simple design are a very good starting point :

A visual graph of Kent Beck's rules of simple design

Find your tools

Back in 2003, after reading Martin Fowler’s Refactoring: Improving the Design of Existing Code book, I decided to give TDD a serious try. I was using C++ at work but we did not even have a nightly build. I had to download and setup CppUnit on my own. As solo endeavor, this was a required step to get into TDD.

Find and setup a tool. Which one should be rather obvious, if your team already uses a unit test framework, stick to it, otherwise, pick the most standard for your language, ex : JUnit for Java (you might as well start searching for a new job where they use a unit testing tool).

Train at a TDD coding dojo

Coding dojos were first invented as a tool to learn TDD. They were started by two french eXtreme Programmers Emmanuel Gaillot and Laurent Bossavit. It happens that I live in Paris, and that Emmanuel came to work as a contractor at the same company I was. I learned that he was organizing a weekly coding dojo open to any developer. That’s how I started attending coding dojos. Looking back, the TDD skills I learned at the coding dojo are just enormous !

If you are serious about learning TDD, attend coding dojos. Whether you find one in your city (ask meetup.com) or in your company does not really matter. If you cannot find any, just start one at work ! Send a public call for interested people (use wiki, mail, posters or whatever), book a room and start hacking ! Emily Bache’s Coding Dojo Handbook seems a very good reference about how to start a coding dojo (Disclaimer : I did not read the book, I only know it by reputation.)

Cover of The Coding Dojo Handbook

Use it

If you’re a professional programmer, you must be spending most of your time writing code. Take this opportunity to use TDD. You’ll be slowed down a bit at the beginning, but as both your code and your skills improve, you’ll get your time back manyfold.

I remember one of my first professional use of TDD was to write a small parser. A few weeks later I was asked to make it faster. Having tests around it made it easy to optimize it without breaking it.

Deliberate practice

In The first 20 hours, Josh Kaufman explains that deliberately practicing specific topics is a more time effective way of learning than simply crunching hours of practice.

My friend Thomas Pierrain is used to regularly practice short 30 minutes katas to sharpen his programming skills. Katas can be found at codingdojo.org, at cyber-dojo.org or in The Coding Dojo Handbook.

Read

Meanwhile I was doing all this, I also spent a lot of time reading on the subject. At the time, there was a lot of things about TDD in the C2 Wiki, so I spent a lot of time there. Since then, I stumbled upon a few books that helped me to understand some aspects of TDD :

Cover of GOOSGT

Practice advanced topics

The TDD road goes on forever, testing has a lot of tricky topics. Once you’ve mastered the basics, it’s quite interesting to explore and practice more complex subjects. Here are a few things worth trying out :

  • Use automated IDE refactorings to keep the code compiling all the way through a kata
  • Do the same kata twice, using top-down and bottom-up styles
  • Do refactoring katas to learn how to work with legacy code
  • Do UI katas, to learn how to test the UI
  • Learn how to deal with DB
  • Learn how to handle remote services

If needed, invent your own katas to deliberately practice these topics and others.

The pitfalls

As any road worth walking, the TDD path is not linear and smooth. Before fully mastering TDD, you’ll regularly wonder if you’re on the right track. As any practice, TDD has pitfalls. I’ve fell into some quite a few times. I guess that’s part of the learning process.

Emerging Design

There’s always been a lot of misunderstanding around this topic.

Bad smells in your code make your tests harder to write. If adding a test is painful, that’s an indication that something could be improved in your design. It’s then up to you to know what. Once you’ve figured out what you want to change, use your existing tests to refactor your design first. Only then, add this new test.

As you can see, the tests will give you more feedback about the design of your code, but they won’t tell you what to do. That’s where your coding skills will help. This is particularly true about algorithms. Don’t expect a good algorithm to magically appear as you do the simplest-thing-that-could-possibly-work …

As with any rules, there are exceptions. At times, you’ll walk into a problem which emerging design is great. For example, I’ve done the Arab to Romans kata many times, and that repeatedly doing the simplest-thing-that-could-possibly-work yields a good solution.

Mocks

Mocks are useful at times, but be careful not to overuse them. I already wrote about mocks. Too much mocking makes your test suite brittle, ineffective and difficult to maintain ! I’ve been bitten hard by this one on a personal side project, the day I decided to get rid of all the mocks, I shrank the test code size by 25%. Since then I learned about alternate techniques such as :

As an indicator, less than 5% of my tests use mocks.

Metrics

In his keynote at RailsConf 2014 DHH explains the danger of testing metrics.

DHH's keynote at RailsConf 2014

By using TDD correctly, you should get a high code coverage as a side effect. If you get below 80%, you must be doing something wrong. The other metric you should keep an eye on is the total build time. Original eXtreme Programming had the 10 minutes build rule which states that if your build + tests takes more than 10 minutes, you should refactor it.

That’s it ! Things like 100% test coverage or test ratio are complete nonsense.

Pushing it even further

My promise, at the beginning of this post, was that Test Driven Development would make your life as a developer easier. Now let’s imagine that your whole team or company was using TDD. It’s a foundation on which to build a sustainable agile organization.

The mastery of automated testing at organization scale is a key element to continuous delivery, making releasing software a non-event, and as stress-free as possible.

Full adoption of TDD can yield to incremental architecture which delivers features faster, by skipping the conflictual arguments about supposed future needs.

Finally, TDD can simplify your processes and tooling. Team-wide TDD results in a steady flow of features on top of which it is easier to create simple and effective processes and tools.

The road is long, sinuous and at times rocky, but so are the rewards.

Most Scrum Teams Are Not Agile

Being agile is about adapting to change and continuously improving. I’ve seen (and been) in too many teams blindly following Scrum (Scrum Zombies) without figuring out how to continuous improve. The most obvious symptom is a boring (or no) retrospective.

Usually, it did not start that way, people had good intentions, and tried to follow the Scrum cookbook. Unfortunately, without any guidance or extreme perseverance, it is plain too easy to mess up the retrospective. If no concrete actions are scheduled at the end of the retro, if the same problems keep coming up at every retro, or if no problems at all are raised during the retro : your Scrum is somehow broken !

One of the promises of Scrum is to keep code quality high, in order to be able to adapt to late changes. Without a good retro to update the coding standards, the working agreements, or to spot and organize large scale refactoring, this will not happen.

One of the agile principle explicitly states the need for motivated team members. In Drive Daniel Pink explains that one of the ingredient for motivation is autonomy. As a way to fix recurring problems, effective retrospectives will create autonomy, and enable motivation. Dysfunctional retros will slowly kill both …

Although continuous improvement at all levels is one of the most important element in your process, it needs a bit of practice to setup right. After trying different approach in different teams, I compiled a list of the things that worked for me :

The cover of the Daniel Pink's "Drive" book

How to do successful retrospectives

Start !

Sounds obvious ! The first step is to schedule a recurring meeting and invite all the team. Someone should take care of facilitating. If you want to improve things, do this yourself at the beginning ! Once the practice is in place and everyone sees the benefits, you’ll be able to get some help.

Here is a crash-course about how to organize and drive your first retrospective. If your team is distributed, you’ll need a slightly different setup. In my previous team, we had success using Trello, you can read more about it here.

Just Do It picture

Make sure everyone talks

Retros should not be “just-another-boring-meeting” ! People should be excited to be there and to solve their recurring problems. I’ve seen retros where no one would speak, as if there was absolutely nothing to improve ! I’ve also been in retros where people raised collaboration issues, and came up with drastic improvements to the way they work, like adopting pair-programming for example.

There can be many reason why people don’t speak : habit, organizational culture … Whatever the cause, if you show them the path, if you demonstrate that retro work and that it is safe to speak, you’ll get them to participate.

Here are a few tricks to guide a team there :

  • It is said that if someone does not speak in the first 5 minutes of a meeting, he’ll remain silent for the rest. That’s why energizers work. They force everyone to participate to a Fun activity right from the start. Fun Retrospective contains a lot of engaging energizers.
  • Bring food ! Having food at work was one of Kent Beck’s main advises in eXtreme Programming, Embrace Change. Food is social and create a more relaxed and safer atmosphere.
  • Before you start the meeting, it might be useful to repeat the Retrospective’s Prime Directive.

Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.

  • As the animator, you should make sure the discussions don’t degenerate into some kind of trolling or blaming. If it’s the case, remind that this is not the way the retro is meant to work. In worst case, give a 5 minutes break to everyone to calm down.
  • If needed, have a private discussion with people outside the retro to make sure that they understand the “Blame the process, not the people” principle of the retro well enough.

Dealing with “bad” behavior in retros is a wide topic which I am only scratching the surface here. I guess I could write a full post about it.

The cover of the "Fun Retrospectives" book

Get out of with actionable tasks

If you want a sure way to screw up your retros here it is : end the first one with no actionable things to do ! People will learn that it’s a useless pscho-blabla meeting for agile softies.

This should be the absolute priority during the first retros. There are various kind of actionable tasks. Teams can adopt new conventions, decide to tackle some specific refactoring, or build a small new tool …

Actionable items should be small enough to be completed in one sprint. This is fine for refactoring a class, adding a SonarQube rule or asking for something from another team. What about larger tasks ? Suppose you just identified a large refactoring to do, how do you get started ? I know 2 strategies for that :

  • Only identify the first step of what you want to start. At least, that’s enough to get started and learn what to do later.
  • Agree on a Mikado discovery task to understand what needs to be done. Code is not the only thing that can be refactored with the Mikado method ! People have used it to transform organizations !

It’s also a good habit to book the rooms for extra time after the official retro time. Nothing is as frustrating as being interrupted while investigating a promising improvement !

Finally, I think it’s a good practice to review what happened of the improvements that were selected during last retro. It stresses the importance of doing what was scheduled in retrospective. It also gives a chance to investigate the reason why they were not done !

The cover of the "Mikado Method" book

Put them in the sprint

When actions are selected in the retro, you should add them to the coming sprint before it starts. Obviously, you’ll add non business related items in your sprint backlog. Whatever you might have hear from agile zealots, do it ! Process improvements are fist class backlog citizens, just don’t discuss them with your product owner.

If you want a chance to deliver what you committed to in your sprint backlog, you’ll need bandwidth for that ! They are many ways to do get that. Some teams use slack time, others reserve an ‘improvement day’ every sprint. My personal favorite (and the one we’ve been doing at work) is to estimate the improvements in story points and reserve a fraction (ex 20%) of your story points for improvements.

You can try to negotiate your improvement ratio with your product owner … or you might also just set it yourself ! The team is responsible for the quality of its work. Better be sorry than ineffective. If you stick to your ratio and only work on the most important improvements, it’s usually pretty easy to justify working on them. Plus if you manage to go under the radar for a few sprints, the results of the improvements should speak by themselves.

Do them as soon as the sprint starts

One last thing. Start to work on your improvements as soon as the sprint starts.

Improvements are similar to investments : you invest in process, tools or code in exchange for more value creation downstream. Once you’ve decided to invest in something, what’s the point of waiting 1 week ? Plus if you wait for later in the sprint, you run the risk of having unfinished improvements at the next retro, which might interfere when prioritizing new ones.

Continuously improving teams

Being part of a continuously improving team is easier to live than to describe. It feels like the future is bright. Once a team has mastered continuous improvement, people can be optimistic that they’ll manage to adapt to change later down the road :

  • They could switch gears and go full speed on a particular re-architecture
  • They could change their working agreements to adapt to new constraints
  • They could re-focus their efforts to handle a maintenance pike

At the end of the day, bottom-up continuous improvement makes everyone’s lives easier. Developers experience more autonomy while improving their productivity, they can do good work (which also means spending less time bug-fixing). Product owners learn that they can trust the team to do their best. Sponsors get more value for their money.

Agile teams bend so they don’t break !

A Straightforward Way to Scale to More Than 1 Scrum Team

How come the “agile scaling” landscape seems so daunting and bloated ?

Being agile should be about taking baby steps, doing things incrementally, starting with the simplest thing that could possibly work, slowly but continuously improving and trying out experiments.

Here’s a real-life 2 hours change that kicks-off a very efficient organization for a few scrum teams.

A guy jumping from a cliff into the sea

“SafeLess” : everything will go fine as long as you follow the principles

A classic story

Without doing anything about it, there are a lot of situations in where Scrum teams will collaborate inefficiently. For example if you are a developer within a medium or large company, suffering from communication loss between your team and others. Or you could be the owner of a software startup, needing to dramatically grow your dev team.

Whatever your situation, without good collaboration, the output of two Scrum teams is bound to be a fraction of the sum of their individual outputs.

Our own situation

We are a group of 4 teams that spun out of the R&D division. We are working to build a highly reusable component for the future versions of Murex’s main product.

While in R&D, teams were aligned with technologies. Now shifting to a product focus, this layered team structure makes it hard for us to organize efficiently. To make things even more tricky, the component we are building is something huge by itself, and we really need to find a way to deliver it incrementally.

This tech-oriented, low synchronization organization of team backlog was really underdelivering. It was not rare to see stories jump from one team to another, as dependencies were discovered, taking one full sprint every time. Integrating end to end features often took a few sprints instead of a few hours …

Clearly, we needed to do something.

The simplest things that could possibly work

Hopefully, all teams were following Scrum. We first had a look at scaling frameworks, especially since other parts of the company are moving to SAFe but we found that they required too much budget and re-organization for our means (remember, we are just a few motivated developers).

While we were discussing what to do, someone had an idea that was simple, cheap and easy : “Let’s start by doing all our scrum ceremonies together”.

We took the opportunity to add a ‘product’ retro after the teams retros, and a ‘product’ planning just before the teams plannings. We were hoping that regular higher level retros would bring continuous improvement at the product scale and bring in all the other practices required to make it work.

The situation now

It’s now been 2 sprints that we have set this up. Every 2 weeks, Friday is what we call Demo-Day. It’s a meeting heavy day where all the teams have their scrum ceremonies together

  • Product demo
  • Team retros
  • Product retro
  • Product planning
  • Team planning

Sure as hell, 1 day of meetings is exhausting, but unfortunately, it is not possible to efficiently grow a team without increasing the communication overhead. The good side of the coin is that it allows the teams to focus on building valuable stuff during the 9 other days.

Here are the first effects we have seen.

Improved team spirit & product focus

The first noticeable effect was on team spirit. Having a demo and planning for the whole team showed to everyone that we are all pulling towards the same goal. It helped everyone to understand what his current role is in this greater scheme, but also ways to tweak our individual roles to bring more value.

Visible problems

The second good effect is that problems are now visible. If teams are not working in the same direction, it’s visible at the demo and plannings. If a team delivers a story too late for another one to integrated it, it’s again visible at demo and planning.

Another example : after the product planning, Product Managers had to admit that they had not managed to feed high value stories to all teams. They asked to do a pre-planning preparation meeting (which is a standard practice in LeSS for example)

Better continuous improvement

During our first team retro in this setting, we directly stumbled upon on a recurring systemic issue that we never managed to do anything about. Instead of going around in circle on the topic again, we pushed it to the product retro. We worked on another team related problem, for which we scheduled improvement actions.

During the product retro, we raised our recurring unsolved issue. With everyone in place, people higher in the organization had the chance to understand its consequences. Eventually, we managed to come up with concrete actions.

How to do it

Pre-requisites

There’s only one thing required : that the teams are already following Scrum. All the rest is easy stuff.

This technique is a bottom-up agile adoption. If you want to switch your whole company from waterfall to something more agile, take a look at SAFe.

Organizing the Demo-Day

Here is our planning for our demo day

Time Meeting Who Details
10h – 12h Demo Everyone 30m per team |
12h30 – 14h Team Retro Teams Every team has a different retro in a different room |
14h30 – 15h30 Product Retro Scrum master, volunteers, and decision makers Decision makers are important to be able to take actions |
16h – 17h Product Planning Product managers or owners, volunteers Product people present what they would like to see in the product in one sprint |
17h – 18h Team Planning Teams Every team has a different planning in a different room |

We had to negotiate a bit with other people in the company to get enough rooms for all these meetings at the same time, but all in all, it did not take more than 2 hours.

All meetings are open to anyone, everyone should have the right to come to any of them !

Obviously, that’s a long day ! It’s also full of team energy. In 2 sprints, we found the following improvements :

Food

We pre-order food to be delivered at work, so that we can all eat together. Did you know that food makes retros more efficient ?

Product Retro

You might have noticed that the product retro is only 1 hour long. To make it all fit in one day, we had to cut some time here and there … In order to gain some time on the product retro, we decided to pre-fill its ‘gather data’ phase.

During team retros, if people find product scale issues, they can directly save them for the product retro items (As we are distributed, we use Trello for retrospectives). This way, when the product retro starts, the gather data phase is almost done, pre-filled with genuine points.

Keep the energy high

One full day of meetings is long. People get tired. In order to keep the energy high and the overall experience fun, we deliberately added some fun throughout the day :

  • Energizers at beginning of meetings
  • Board games during breaks
  • End of day celebration outside the office. You could go out and have a drink all together for exemple.

The Timeline board game box

We had fun playing this game between the meetings

Preparing the product Backlog

Depending on your situation, you might (or not) have a prioritized product backlog. My advice is to start with what you have.

If you are scaling your single team to 2, keep a unique backlog for both teams and create 2 feature teams. You’ll be heading to the LeSS organization, which you’ll be able to refer to.

If you are applying this on existing scrum teams with their own backlogs, it might be easier to create a product backlog for the product managers. This is more akin to what SAFe suggests. It’s not as straightforward as having a single backlog for everyone, you’ll need to add some links between team and product stories to be able to track progress. Nevertheless, it provides visibility to everyone. As a side note, this is what we actually did.

Keep in mind that it’s only a starting point anyway, product retrospectives might transform all this down the road any way.

Start where you are now !

The most important thing to do is to start ! There are always a ton of reasons why things are not ready and need more preparation. Remember the agile principles : integrate early and often, adapt, experiment … Here are few examples of bad reasons not to start

  • You cannot get all the good people in the room : start, invite them anyway, and send them a report of what has been decided without them. I cannot promise that’s it’s going to work at the end, but at least, it will create some discussions
  • The product backlog is not ready : start, and see what happens ! It will make it clear to everyone that product backlog is super important. People will organize to provide enough product features next sprint.
  • You need some other regular meetings for X, Y or Z. For example, Scrum of Scrum has daily SoS Meetings. Start anyway, if there’s a need, people will ask for these extra meetings, which will save you some goodwill. You might also discover that you don’t need these meetings at all and save some time !

With a product retrospective every sprint, important issues will get addressed !

Just Do It

Does ‘Agile Scaling’ even exist ?

We did this on 4 teams. I have no ideas how it would work with more teams. We did not use any framework, even though we took ideas here and there. What we really did is to follow the agile principles, for example :

  • KISS
  • Do the simplest thing that could work
  • Baby steps
  • Continuous improvement
  • Experiment

Others have noticed similar things :

Agile scaling frameworks might be a good starting point (the Shu in Shu-Ha-Ri), but only as long as the agile principles and values have not been understood by the organization.

Incremental Architecture, a Cure Against Architecture Astronauts

Back in 2001, when I started to code for a living, fresh out of school, I was mainly doing a form of cowboy coding. After a few months of maintaining my own mess, I started to recall my university lessons : we should be doing design before coding …

When I was asked to re-engineer the ‘wizards UI’, I paused my coding to design something clean from scratch. It worked quite well at first : the overall code was a lot simpler and contained a lot less duplication than before. Seeing this new shiny UI, product people asked for new features. Unfortunately, I hadn’t thought of them when designing this little framework. I was almost back at my initial situation.

That’s how I started to look for another way to design software. At about the same time the eXtreme Programming book fell into my hands. That’s where I discovered the idea of incremental design and architecture.

Front cover of the first edition of the XP book

What is Incremental Archi

Let’s start with the antithesis of incremental architecture :

Astronaut Architecture

The term “Architecture Astronaut” was coined by Joel Spolsky back in 2001. If you haven’t read this classic post yet, I strongly encourage you to do so. Basically, he explains that we should not be impressed by architects going over their heads talking about too abstract stuff.

Incremental is the exact opposite of astronaut architecture

Two Schools to Software Architecture

Traditional architecture is about taking up-front choices that will be difficult to change. Incremental architecture is about preparing for non-stop change and taking decisions as late as possible.

The idea in incremental architecture is really simple : keep your code simple, clean and automatically tested in order to be able to simply adapt your code and architecture when definitely needed.

Pros and Cons of incremental architecture

The first reaction of most software engineers (me included, remember how my story started) is that it can only work on trivial stuff. After practicing it for about a decade, I am now convinced it works most of the time. I’m not alone, James Shore (who wrote the more on the subject) also shares my view:

Common thought is that distributed processing, persistence, internationalization, security, and transaction structure are so complex that you must consider them from the start of your project. I disagree; I’ve dealt with all of them incrementally.

Two issues that remain difficult to change are choice of programming language and platform. I wouldn’t want to make those decisions incrementally!

I would add published APIs to this list.

Granted, there are situations that incremental architecture alone cannot handle, what about its good points then ?

In all the other cases (and that means most of the time), here is what you get :

  • As you won’t need to deal with future use cases, you’ll do less work
  • That in turn, will keep your code simpler, decreasing time to release new features
  • As change is built-in, you’ll be able to improve your architecture in ways you could not have imagined from the start !

Front cover of the Art of Agile Software Development book

If you cannot see how this could possibly work ? Read on !

How to do it

eXtreme Programming

As I said earlier, incremental architecture emerged from eXtreme Programming. It won’t come as a surprise that in order to work well incremental architecture requires the XP practices to be in place. In particular, the code base should be automatically tested, the continuous integration cycle should take less than 10 minutes, the design should be simple. The team should be good at doing refactoring.

Don’t expect to be able to do incremental architecture without these practices in place. But this alone might be enough already !

Front cover of the Martin Fowler's refactoring book

Architecture Vision

At work, where our team consists of 9 developers, it’s not always that simple to coordinate and all pull in the same direction. That’s why we find it useful to share a very long term architecture vision (Enabling Incremental Design and Evolutionary Architecture). This will help people to make coherent decisions when hesitating between 2 alternate designs.

The vision can be the result of the work of a pair, or a mob brainstorming or whatever. Building this vision is typically an activity where experienced programmers can contribute a lot of value.

Once this vision is shared and understood by the team, every time a pair has to work on a story, they can orient the design towards it. But always as little as possible to finish the work at hand, remember the XP motos KISS (Keep It Simple & Stupid) & YAGNI (You Ain’t Gonna Need It.

One final word … a vision is just that : a vision ! It might turn out true, or false, be ready to change it as circumstances change.

Spikes

At times, even with a story in your hands and a long term architecture sketch on the whiteboard, you might have difficulties to know how to change your design to fulfill both.

As always in XP, in case of uncertainty, use Spikes ! Spikes are short time-boxed experiments of throwaway code, which goal is to answer a specific design question.

How to mitigate the risks

What about these topics that don’t yield to incremental architecture ? What if you discover late that you need to change your platform ? Or your API ?

Obviously, you should think about these questions up-front. Hopefully, there are usually not that difficult to answer. But, over time, Non-Functional-Requirements and technologies change. Large and long living systems are particularly likely to need to change to a new platform someday.

Unix had the answer : build your system out of small tools, that do only one thing well, and that communicate through a standard protocol. Systems built that way can be re-written one piece at a time.

Ken Thompson and Dennis Ritchie, the creators of Unix

Photo from WikiMedia

The modern version of this is the micro-services architecture. Incremental architecture allows you to start with a monolith, split it when you need to, and replace micro-services as needed. With the safety of simple code and a great automated test harness. Interestingly, successful software systems that were architectured up-front also take this road … without the safety !

The Architect

Good news : no more PowerPoints and a lot more coding with the team ! Here is what’s expected from an incremental architect :

  • To code with the team. As Bertrand Meyer once said “Bubbles (aka. diagrams) don’t crash”, it’s plain too easy, and wrong, to mandate architecture without living with the consequences
  • To come up with more ideas when drafting the long term vision
  • To keep an eye on the ‘long term’ while being the navigator in pair programming
  • In the second edition of the XP book Kent Beck suggests that the architect should write large scale tests to stress the system and demonstrate architecture issues to the team
  • To delegate as much as possible to the team. However smart the architect, the team as a whole is smarter ! Delegating architecture increases motivation and the quality of the outcome.

End of the story

I’ve been practicing incremental architecture and design for a long time now. It made my life a lot simpler ! Most architecture questions become backlog items to prioritize.

One last advice : be prepared to re-read Joel Spolsky’s article whenever you get caught up in architecture meetings …

How to Get Your Team to Do Code Reviews

As software developers, we very always often get to work in code bases that are not perfect. In this situation we have 3 choices : leave, grumble, or make some changes ! Team wide code reviews are a recognized way to increase the quality of the code.

Unfortunately, installing code reviews as part of the daily work habits of a team can be very challenging. When I joined my team 3 years ago, no one was doing any kind of code reviews. With a small push here and there, I managed to get the team to adhere to a strict 4 eyes principle (full story here).

Here are a few strategies that I have either used or seen that should get your team mates to do code reviews.

Overall principle

Even if you are at the bottom of the org chart, you have far more influence than you would first think. My favorite way of bringing change is to demonstrate a valuable practice :

  • First, you need to be trustworthy
  • Then, do the practice you want to introduce
  • Make sure it is seen as valuable
  • Be ready to forgo the credits of the introduction of the practice
  • Keep on until people start to copy what you are doing

As someone famous said

A man may do an immense deal of good, if he does not care who gets the credit

I won’t go in the details about how to be trustworthy, which could be a post of its own. Basically, putting our customers interests first, speaking the truth and avoiding to appear dogmatic can get us a long way already. The Clean Coder is an excellent read on the subject.

Front cover of the Clean Coder book

Strategies

If you have retrospectives in place

In this case, you already have a place and time dedicated to discussing changes to your working agreements. Expressing your concerns about code quality (or another problem related to code reviews) and suggesting code reviews as a way to fix that problem might get a quick team buy-in.

If you don’t manage to get a definitive buy-in, try to get the team to ‘beta-test’ code reviews for a while. If the experiment demonstrates value, it will convert into a full fledged working agreement.

If you practice collective code ownership

Unfortunately, if you don’t have retrospectives in place, or if you did not manage to get your team to discuss code reviews in retrospectives, yo’ll need to find another way to introduce them.

If you have collective code ownership, it should be ok to comment on your team mates code (if not, jump directly to the next strategy). In this setting, just start to do some code reviews for others ! Make sure your reviews are helpful and ‘nice’.

You’ll need to stick to doing code reviews long enough before people actually start to mimic you. Reserve some time in your daily agenda for code reviews. Your goal is to win over people, so it might be a good idea to start with a selected few at the beginning, preferably people who are more likely to jump in. If asynchronous (tool based) reviews don’t get answered, be ready to fallback to face to face discussions : review on your own, then just ask the author for a few minutes so that you can discuss his change. When you feel someone is interested by your reviews, ask him to review your own code in return.

Remember to always try to get some feedback : ask people what they think of the exercise, keep note of the good points, and adapt to smooth out the rest.

Illustration of a team working collectively

Photo from emotuit

Once you won over your first team mate, involve him in your grand plan to spread the practice, explaining how much you think this could make a difference. As more and more people get convinced, the practice will eventually tacitly become part of your working conventions.

Depending on your context, this might take more or less time. I said it was possible, I never said it would be easy ! Grit, patience and adaptation are key here.

Otherwise

This is the worst starting point, basically, you have nothing yet. The strategy is very similar to the one with collective code ownership, with a different first move.

Instead of providing code reviews to your team mates, start by walking over to them to ask for a face to face code review of your own commits. Use the same tactic as stated before : stick to the same people at first. Once the practice starts to stick within this group, bring in a basic tool to ease up the process.

At some point, you should be asked to review others code, that’s a good sign ! If not, try again with other people.

Continue using the same strategy as with collective code ownership and you should eventually get there !

When it does not seem to stick

There could be many reason why the practice is not adopted. The key for you is to understand why and to adapt your strategy. The reason is often that the perceived value is not big enough, for example :

  • the team is not aware of its problems that reviews would fix : try to make them more visible
  • reviews are seen as too expensive or painful : try better tools or taking more on yourself
  • the team has bigger problems to fix first : spend your energy on these first !
  • reviews just don’t work in your context (ex: your job is to write one time, throw away code) : it’s up to you to stay or leave !

Tools

There are a ton of tools and best practices to run code reviews. It’s important that you know them, so that you know where you are going.

Don’t expect to use the best tools from the start though. At the beginning, your goal is to win over your team mates. In this context, only 2 things matter :

  • It should have almost no adoption curve, so that others start using it
  • It should have almost no maintenance cost, as you don’t want to spend your time doing that

That’s why at the beginning, low tech tools are so great. Spending a month setting up a top notch code review system before the first review won’t work. If your VCS has code reviews built-in, by all means use it ! Otherwise, diff in mails and face to face conversations are a good starting point. You’ll later hook something in your VCS to automatically send mails with commit diffs …

As people gradually get convinced of the value of code reviews, regularly meet and discuss a better setup. This is how you’ll introduce state of the art tools and agree on refinements such as pre or post commit reviews.

Best practices

As a code review champion, it’s very important that you provide great reviews to your team mates. You must become the local expert on the subject ! You don’t want all your efforts to be ruined because one of your reviews has been perceived as aggressive.

A slide from Atlassian presentation about styles of code reviews

There is a ton of resources on the internet about how to perform good code reviews, here are a few :

What’s next ?

Congratulations ! Your team will start to reap the benefits of code reviews. Keep on improving the practice !

To end the story, after a few months of code reviews, during a retrospective, my team (at work) decided to take it one step further and started to do almost full time pair programming ;–)

A Seamless Way to Keep Track of Technical Debt in Your Source Code

I eventually stumbled upon a way to keep track of technical debt in source code that is both straightforward and already built-in most tools : simple TODO comments !

Photo of a screen displaying source code with #TODO comments

How it happened ?

Some time ago, we tried to add @TechnicalDebt annotations in our source code. Unfortunately, after a few month, we came to the logical conclusion that it was too complex to be effective :

  • It involved too much ceremony, which frightened people
  • It made people uneasy to change anything around the annotation instead of sending a call to action
  • As a result, it was always out of date

After a bit of discussion with my colleagues, we decided to replace all these annotations with simple TODO comments.

When the refactoring to do seems fairly obvious (but also premature) we’ll use a straightforward //TODO (example) introduce a factory message. Next time a pairs gets to work on this part of the code, they get the silent opinion of their peers to help them decide what to do about this piece of the code. Other times, the code might be smelly, yet without us knowing what to do about it yet, in this case, we agreed to use //TODO SMELL (example) responsibilities are not clear in this class which is still a TODO comment, but not a clear call to action.

When I started my current side project, I naturally started to use them. They display nicely in CodeClimate.

The pros

Screenshot of the CodeClimate issue dashboard displaying TODO comments

The great thing about TODO comments is that, as a very old programming trick, they are already supported out of the box by most tools IntelliJ, SonarQube, Rails, CodeClimate and I guess many others. Only one day after I refactored to TODO comments, a team mate fixed one that had appeared in his IDE’s TODO tab !

The cons

Some tools, IDEs in particular, tend to assume that you should fix all your TODOs before you commit anything. That’s not exactly how we are using them to track lasting technical debt. So that’s one thing you need to keep in mind.

Tools like Sonar on the other hand, assign a fixed remediation cost to any TODO you have in the code, which is usually not the case at all !

How to set it up in your project

As you might guess, this is pretty easy. Just start adding TODO comments in your code …

Teamwise

It is worth first validating the practice with your colleagues though. There are many ways to do that, depending on your team’s work habits :

  • Use your team Slack (or whatever chat room you use) to share a link to this post (for example) and create a yes/no poll
  • Or if you think you need it, create some wiki page explaining the practice and detailing its rationals in your context, add a yes/no poll, and finally share this page with your team
  • Eventually, if you think that this topic deserves it, setup a meeting with everyone and discuss the point. It might be worth sharing information about the practice beforehand to make the meeting more efficient. You can end the vote with a thumb vote (up : yes, down : no, side : whatever)

Thumbs voting positions

Don’t wait for unanimity to start the practice, majority is enough ! Make sure that people who voted the other way will follow the team practice in the end though. Remember that whatever the answer, discussing team practices is good.

Once all the team agreed on using (or not) TODO comments, mention the practice in your team’s coding conventions or working agreements (which I strongly recommend to have written somewhere). If you don’t have any yet, create some !

Toolswise

Most tools will handle TODO out of the box.

  • Rails comes with a rake notes task to list TODO comments.
  • CodeClimate and SonarQube both lists TODOs as issues in their default config
  • Most IDEs have a ‘TODO’ tab which will display the TODO comments in the project
  • Otherwise, good old grep will very happily find TODO comments in your code

Some tools might require small tweaks to improve the experience :

  • In IntelliJ, in the commit window, uncheck the ‘Check TODO’ checkbox to avoid getting a warning at every commit

IntelliJ's commit window, with its 'Check TODO' check box

  • SonarQube uses the same fixed remediation cost for every TODO comment. It’s up to you to adapt this remediation cost to your context.

What’s next ?

TODO comments are a good starting point to track technical debt. Once you start using them, there are a few things you can do :

First, remember to fix some regularly. Very old TODO comments are technical debt of their own ! Using code quality dashboards like SonarQube or CodeClimate help to continuously improve your code.

If your tools allow it, you might consider setting up a simpler //SMELL ... instead of //TODO SMELL ... or whatever other special comment that might be useful in your context.

Finally, there is a lean continuous improvement practice which consists of logging problems as they occur. Doing this could help your team to decide which technical debt hotspots are the most important to fix. When appropriate, link the problems with the TODO comments. After a few weeks of this, walking through all the problems during a retrospective should shed light on what parts of the code are causing the most troubles.

Edit 2017-04-19

Thanks a lot for your comments ! People have suggested a ton of great improvements over my basic setup :

  • plugins to other tools that also support TODO comments
  • activating automatic sync between issues in CodeClimate and your issue tracking system
  • using custom comments markers
  • adding an ‘X’ to your comment every time you are bothered by the technical debt, tools can configured to assign a higher severity to issues with a lot of ‘X’

How to Mock Your Browser’s Timezone With Jasmine and MomentJS

Last week, I’ve been working at adding a distributed countdown to my Online Planning Poker App. As our team works from Paris and Beirut, I wanted to unit test that it would work well through different timezones. I found a surprisingly simple solution.

What Google told me

I first searched Google to see how to do it. I found 2 answers that looked promising :

Known results for such a simple situation were disappointing !

What I ended up with

After a good deal of dabbling around, I eventually found a pretty simple solution using Jasmine and Moment Timezone :

1
2
3
jasmine.clock().install();
...
jasmine.clock().mockDate(moment.tz("2017-03-23 10:00:00", "Europe/Paris").toDate())

Obviously, the drawback is that it implies setting both the timezone and the time. This should be ok in most of unit tests though, but might be an issue in some cases.

Almost 15 Years of Using Design by Contract

I first read about Design By Contract in 2002, in Object Oriented Software Construction 2. As soon as I read it, I was convinced, today, I still believe it’s a great and fundamental technique. That’s why, I almost never write a contract ! Let me explain.

Phase 1 : DbC ignorance

I started to code professionally in 2001. This was a time where design and quality software meant Rational Rose (a UML design and code generation tool) while I, at the contrary, was just Cow Boy Coding my way out of any problem I was given.

I wasn’t really doing Object Oriented programming, but rather imperative programming, using objects as structs, getters, setters, and classes as a way to organize the code … In this context, my design skills were improving slowly, and I was at the risk of falling in love with a local-optimum practice that would prevent me from growing further.

That’s why I started to read books such as the Gang Of Four Design Patterns, or OOSC2.

Phase 2 : DbC enlightenment

The cover of the Object Oriented Software Construction 2

Reading this book was a profound experience to me. My programming changed fundamentally before and after reading it. The chapter about contracts, taught me what objects are.

One the one hand, Pre and Post conditions can be used in any kind of programming and are just a kind of C assert macro on steroids. Class invariant, on the other hand, is a completely different kind of beast. The invariant of a class is a predicate about an instance of this class that should always be true. For example : field X should never be null, or the value of field N should always be greater than 0.

In some way, grasping the concept of invariant is close to understanding what a class is.

Phase 3 : DbC everywhere

That’s when I started to write contracts everywhere. I was writing C++ code at the time, and my code must have looked something like that :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class MonkeyWrench
{
    bool _isStarted;
    std::vector<Part>* _movingParts;

protected:

    virtual void invariant() const
    {
        assert(_isStarted == (_movingParts != NULL));
    }

public:

    MonkeyWrench()
    {
        this->_isStarted = false;
        this->_movingParts = NULL;

        invariant();
    }

    bool isStarted() const
    {
        return this->isStarted();
    }

    void start()
    {
        assert(!this->isStarted());
        invariant();

        this->_movingParts = ...

        invariant();
        assert(this->isStarted());
    }

    const std::vector<Part>& movingParts() const
    {
        assert(this->isStarted());
        invariant();

        return *this->_movingParts;
    }
    ...
};

I definitely over-abused contracts, it made the code unreadable. Plus sometimes, I was using excessively long and intricate assertions which made the problem even worse.

Hopefully, overusing contracts also taught me a lot in a short time. Here are some of the lessons I learned :

  • DbC is not very well supported, it’s never something built in the language, and edge cases like inheriting an invariant or conditions can become messy pretty fast.
  • Checking for intricate contracts at every method call can be pretty slow.
  • Checking everything beforehand is not always the simplest thing to do, at times, throwing an exception on failure just does a better job.
  • It happened that removing the contract made the code do just what I wanted. It’s easy to write unnecessary strict contracts.
  • Command Query Separation Principle is great ! Having ‘const’ or ‘pure’ queries that don’t change anything make writing contracts a lot simpler.
  • Preconditions on queries are painful. When possible, returning a sensible ‘null value’ works better, nothing is worse than getting an error when trying to call a const query from the interactive debugger.
  • Finally, the more immutable a class is, the simpler the invariant. With a lot of mutable fields, you might resort to have the invariant check that fields are synchronized as expected. If fields are immutable, this simply vanishes.

Phase 4 : DbC hangover

At the same time I discovered all these small subtleties about contracts, I fell upon Martin Fowler’s book Refactoring, improving the design of existing code and started to use Unit Tests extensively. This lead me to the following conclusions :

  • Tests are more efficient at producing quality software
  • Contracts can be an hindrance when trying to do baby steps refactorings as described in Martin Fowler’s book

On top of that, as DbC is not natively supported by languages, no documentation is generated, meaning that most of the time, the callers still have to look into the code. As a result, I was using contracts less and less often.

Phase 5 : DbC Zen

Looking back, I might not be writing a lot of asserts in my code, but I am still thinking in terms of contracts all the time. In fact, there are a ton of ways to use DbC without writing assertions :

  • Use as much immutability as possible. An immutable class does not need to check its invariant all the time, just throwing from the constructor if arguments are not valid is enough.
  • Use conventions as much as possible, for example, constructor arguments should be set for all the life of the object (cf Growing Object Oriented Software Guided by Tests which describes the different ways to inject something in an object)
  • Looking back at my DbC assertions, most relate to null values. Again conventions work better ! At work, we simply forbid passing null values around. If something can be null, it means it’s optional, Java has an Optional<T> class for just that (I’m pretty sure it is possible to do something even better with C++ templates). In this case, if the contract is broken, NullReferenceException will eventually be our assertion.
  • Replace as many pre & post conditions with invariants on the callee, the arguments or the return objects as possible. It makes sense as it’s just making sure we are using ‘valid’ objects everywhere. Again, if these objects are immutable, it makes the whole thing even simpler !
  • To take further benefit of the invariant of immutable objects, introduce new types. For example, instead of changing an object’s state through a command with associated involved contracts, split the class in 2 and make the method a query returning an immutable object, potentially making the initial class immutable as well. Remember, immutable classes mean almost no assertions !
  • Use your language. Ex, instead of asserting that 2 lists remain of the same length, refactor to a list of pairs ! (I know that’s an obvious example, but you get the point)
  • If you are using a statically typed language, use types ! For example, I remember at one project I worked on, we had an bug involving a duration : somewhere in the code milliseconds got mistaken for seconds … We fixed that by replacing the integer by TimeSpan all over the place. Again, that’s so obvious !
  • Eventually, when all else fails, or when it’s just too much overhead, use the simple asserts provided by your language or common libraries.

To come back at the previous code section, this how it could be written without assertions :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class MovingMonkeyWrench
{
    const std::vector<Part> _parts;

public:
    MovingMonkeyWrench() : _parts(...) {}

    const std::vector<Part>& parts() const
    {
        return this->_parts;
    }
    ...
};

class MonkeyWrench
{
public:
    MovingMonkeyWrench start() const
    {
        return MovingMonkeyWrench();
    }
    ...
};

Details are omitted, but it’s easy to see how shorter the code is.

Conclusion

When applying all the techniques above, you’ll see that cases for explicit assertions are rare. Less assertions also workarounds the issues coming from the poor support for DbC : no documentation and intricate cases.

In the end, assertions made my code more ‘functional’. I’m not alone to have done the same journey, and if you are interested you should read Eric Evans’ DDD book where he presents things like immutable value objects and specification objects.

My Ultimate Jira Personal Kanban

A few years ago, I wrote about how I started to use Jira as my personal Kanban board at work. A lot of things have changed since then, which brought me to update my board and make it even more productive !

The context

During the almost 18 months since I wrote this first post, a lot of things have changed in my daily work (hopefully : I’m not doing the same thing again and again !). Essentially, I got involved in more projects, some of which involve people from all around the company and some of which don’t require any code to be written. For example, I’m now engaged in our Agile Community of Practice, where I sometimes contribute content.

Here are the consequences on my work :

  • I have more tasks to deal with, not necessarily more work, but still more tasks
  • I have more sources of tasks : tasks can come from any of the projects I am involved in
  • I have more tasks depending on other people, and that are in a WAITING state meanwhile

I had to adapt my personal Kanban to this new workload.

The changes

As I explained in the previous description of my Jira Personal Kanban, I am using a custom project and Kanban board to aggregate all my tasks from various projects, in order to see everything in a single unique place. Here are the changes I’ve made since, so if you haven’t yet, it might be a good idea to read that previous version first.

Quick filters

In his post Maker’s Schedule, Manager’s Schedule Paul Graham explained the challenge of having a lot of non-programming work to do everyday for programmers. He then advises to use slots for different activities during the day, in order to keep uninterrupted chunks of time to do creative work. To apply this technique, I reserved ‘Unbookable except for X’ slots in my calendar everyday.

I had previously been using Swim-lanes to track work from different projects. This turned out not to scale very well to more projects : it made the board messy, and I kept being distracted by all these other tasks. I ditched all the Swim-lanes (not exactly, I kept one for urgent issues only). Instead of Swim-lanes for tracking projects, I now use Quick Filters. I created such filters as With Project X and Without Project X. During the day, when I want to focus on Project X, I use quick filters to only show tasks related to it.

Quick filters screen capture

Day markers

I have a daily routine of checking what’s on my plate and deciding what I’d like to achieve during the day (picking the right time to do this is an art in itself). In order to keep track of this, I use special day marker tasks : as ^^^ TODAY ^^^, ^^^ TOMORROW ^^^ and ^^^ THIS WEEK ^^^. This tasks are always in my TODO column, and will never be completed. I move them around to mark what I expect to finish at different time horizon. Ex : everything above ^^^ TODAY ^^^ should be finished before the end of the day.

Again, this helps me to focus on today’s activities, and to do just enough prioritization.

Day marker tasks screen capture

One last thing here, you’ll have noticed the Epic for these special tasks. It’s a way to identify them in JQL queries.

WAITING flag

Quite often, you have tasks waiting for someone else. That’s surely not the most efficient situation, but once you leave the comfort of your focused dev team, handoffs are often the norm (at least until the lean principles spread in every part of the business). Status of waiting tasks is worth checking regularly, but very certainly not many times per day !

Again, leaving them in my board created useless distraction. I have now taken the habit of renaming the tasks I’m waiting for with a [WAITING] ... prefix. On top of that, I created 2 quick filters WAITING and Without WAITING to quickly check and then forget about waiting tasks.

Waiting tasks screen capture

Watching tasks I’m not the assignee of

On some occasions, we might be two of us working on the same task, or I might want to keep an eye on a task to know if something is needed from me. As there is only a single possible assignee in Jira, I changed my global filters to also include tasks with a custom label pbourgau-watch. Any time I want to add a task in my board, I just add this label to it.

Screen capture of a task description I'm not the assignee of

Getting the Lean reports back

In order not to have too many old tasks in my board, I used to filter out old items in the global filter. This did the job, but at the cost of invalidating the lean reports (cumulative flow and control charts). In order to get these back, I removed this constraint from the global filter, and created yet another quick filter Without Old which I almost always keep on.

Control chart screen capture

Scripts

Global Filter

1
2
3
4
5
6
7
project in (POP, POPABTODO, "Development Engineering Program", COPA)
AND type != Epic
AND (Assignee = pbourgau OR
    Co-Assignees in (pbourgau) OR
    mentors in (pbourgau) OR
    labels in (pbourgau-watch))
ORDER BY Rank ASC

Quick Filters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- With "Project X" + Day marker tasks (Epic link ...) + tasks containing "BRANDING"
project = "Project X" or "Epic Link" = POPABTODO-410 or summary ~ "BRANDING"

-- Without "Project X"
project != "Project X" and summary  !~ "BRANDING"

-- Without Old
status not in (DONE,CLOSED) OR updated >= -14d

-- WAITING
summary ~ 'WAITING'

-- Without WAITING
summary !~ 'WAITING'

Things that did not change

I still use a WIP limit on the In Progress column, display the Epic in on the cards and special use custom color coding for tasks :

1
2
3
4
5
-- Tasks with an imminent due date become red
duedate <= 1d or priority = "1-Very High"

-- Tasks with a due date are orange
duedate is not EMPTY

The result

Overall, this is how my board looks like :

Full board screen capture

I guess I’m a kind of personal productivity geek … but I believe it’s a skill of utter importance for developers, especially when they get a bit of experience and are not fed ready made tasks to do.