A constraint is an artificial challenge during an exercise designed to help participants think about writing code differently than they would otherwise. Some constraints are an exaggeration of fundamental rules of object oriented design and are applicable during your day to day work. The more extreme ones might still help you understand the underlying concepts of object orientation.
Brutal Coding Constraints
The Brutal Constraints constraint is a composite constraint like Object Calisthenics, a combination of several constraints, some of them already difficult enough on their own. One particular combination that we like is
- No Conditionals, i.e. no
whilecan be used as conditional too and is not allowed as well.
- No Loops, i.e. no
repeat untilor whatever repetition constructs your language offers. Together No Conditionals and No Loops are sometimes called Cyclomatic Complexity One.
- TTDaiymi (TDD as if you Meant it), a very strict interpretation of the practice of TDD. This is optional, a "bonus" constraint for experienced developers. If you never heard about it, just ignore this one.
- No Naked Primitives, i.e. wrapping all "primitive" values, e.g. booleans, numbers or strings. Also general purpose containers like
Setare considered primitive. In extension all generic types of your language are primitive because they are not from your domain. A generic date (e.g.
java.util.Date) is not from your domain even if you use dates, because it either does not define all methods you need or it defines other methods you do not need.
- No void, i.e. all functions must return something, methods with no return value are forbidden.
- Immutable, i.e. all data and data-structures must be immutable.
Violating the Rules
When practising these Brutal Constraints with some kata, Martin and I were not able to find an implementation that would satisfy all constraints right away. We usually allowed violations in the beginning and refactored towards the constraints after the green phase. Sometimes we would leave a violation in for a few red-green-refactor cycles. It helped us to go through the list in each refactoring step to make sure we did not forget any constraint. It happened that we had put a condition somewhere in the code and forget about it - we are just that used to using conditionals and loop constructs. Because participants often ask for it, here is a list when to be strict about the rules. It is allowed to violate constraints:
- temporary until you fix them during the next refactoring step;
- temporary until you fix them after triangulating a solution, probably during a larger refactoring step after several cycles, e.g. after the third test;
- if an used framework requires it, e.g. using a
- if the testing frameworks requires it, e.g. JUnit test methods are void methods and
List<Object>which is a primitive container.
As I said before, Martin and I aimed for a really difficult exercise and I think we offered the only expert level session at ATD2014. And yes, this exercise was hard. The difficulty of each constraint was multiplied by their combination. For example I wrote about combining TDDaiymi, No Naked Primitives and No Conditionals last year. The attendees of the workshop agreed, "it was really difficult" up to "WTF" ;-). Brutal Coding Constraints are definitely too difficult for programming beginners, who even struggle with the concept of immutability.
An exercise like the Brutal Constraints can get frustrating easily. We told the participants that we made the session impossible on purpose, so they would not feel bad when getting stuck. When creating the workshop we got stuck ourselves several times, so we knew what to expect. During the session we paid close attention to the participants' mood and were prepared to offer hints on how to proceed without violating constraints. All participants worked hard and enjoyed the exercise.
Why practise like that?
What about Functional Programming?
The Brutal Constraints focus on Object Oriented Programming. No Naked Primitives is the main driving force to create more types. On the other hand, constraints 1, 2, 5 and 6 might not challenge in Functional Programming. Instead of explicit conditionals some languages provide an
Maybetype and filter operations remove unwanted elements from containers. Most loops are unnecessary because containers provide
foreachor similar operations. Also a recursive function call is not a loop. Pure functions and immutability are base concepts of functional programming anyway. I would like to see a solution following the above constraints in Clojure or Haskel. I am unsure how No Naked Primitives translates into Functional Programming.
In general the actual assignment, i.e. the problem that participants are asked to solve, does not matter for a kata but we wanted a problem that did not support the constraints. (Evil grin ;-) Such a problem would have a linear or higher dimensional structure with a need for looping (which is not allowed) and business rules, which are conditionals (which are not allowed either). We started with the classic Game of Life but it took us too long to reach a point where the constraints forced us to think harder. So we switched to a smaller problem, finding the winner of a game of Tic-tac-toe, which worked well for us.
Hints for Facilitators
If you plan to host your own Brutal Constraints exercise, your first priority is to help the participants to meet the constraints. It is easy to miss an
voidmethod. We recommend printing the list of constraints and TDDaiymi rules as handout for each pair in the workshop. Second you need to pay attention to people's mood, as I described above.
For a short workshop it would help to force participants into situations conflicting with the Brutal Constraints as early as possible. One way to do this is to start with a prepared code base that already contains the first loop or conditional which needs to be removed. But then the list of supported programming languages for the workshop is small, ruling out less popular ones. Another way is to ask participants to follow a list of predefined test cases. While this allows any language, it impedes the creativity of solution finding. We still have to find a good list of test cases though.
But why should we stop here? We can make the exercise even more difficult. A suitable constraint to add is No Duplication, i.e. being very aggressive about duplication in the code. Unfortunately detecting duplication is less straight forward than following constraints 1, 2, 4, 5 and 6 which just deny certain reserved keywords or library classes. Another option is to add Baby Steps to force smaller working steps and Baby Steps has been combined with TDDaiymi already. When practising the constraints we committed every five to six minutes without problems.
Thanks to Martin Klose for creating the Brutal Coding Constraints with me. Pair facilitation is just so much more rewarding than solo work.