Wiki Fan de Test

The card set - printing material[]


Here is a 1st attempt on gamifying Sw Craftsmanship practices (nicknamed here CCC for "Clean Code Craftsmanship from Uncle Bob's book). This card set has been tested already in a private company which agreed to let the content under the Creative Commons licence.

So, here it is. Please download the PDF, print it, cut pages, fold them and glue them to get cards.

Cards Description[]

Cards are gathered into 5 families

  • Design: generic practices related to design
  • Testing: practices related to code testing and reviewing
  • Coding: practices related to code generation
  • Mindset: practices related to expected behaviors
  • SOLID: key designing principles

Within each family, there are Relatives (appreciated members) and Foes (the one we should reject but are always trying to come in your code as spongers)

Design Family[]


Coding and designing are extremely intertwined. This set of patterns takes care about higher level coding matters

Structure over convention[]

Enforce design decisions with structure over convention. Naming conventions are better than "over configurabilty", but they are inferior to structures that force compliance.

Mind-sized Components[]

Break your system down into components that are of a size you can grasp within your mind so that you can predict consequences of changes easily (dependencies, control flow, …).

Name matches Level of Abstraction[]

Choose names that reflect the level of abstraction of the class or method you are working in.

High Cohesion[]

Cohesion is the degree to which elements of a whole belong together. Methods and fields in a single class and classes of a component should have high cohesion. High cohesion in classes and components results in simpler, more easily understandable code structure and design.

Loose Coupling[]

Two classes, components or modules are coupled when at least one of them uses the other. The less these items know about each other, the looser they are coupled. A component that is only loosely coupled to its environment can be more easily changed or replaced than a strongly coupled component.

Misplaced responsibility[]

Something put in the wrong place. Maybe the architecture is not “SOLID” and the Principle of “Least Astonishment” may be also violated.

Over configurability[]

Prevent configuration just for the sake of it – or because nobody can decide how it should be. Otherwise, this will result in overly complex, unstable systems.

Artificial coupling[]

An artificial coupling is a coupling which is only there for technical reasons and should not be coupled

Example: Time depending on Watch (time should be meaningful without a Watch)

Testing Family []


Craftsmanship is also about testing: ATDD and Test First being the most obvious patterns but everything that enables built-in quality is also part of this set of practices for in agile testing, we need to prevent bugs rather than finding them.

Automated ATDD[]

Use automated Acceptance Test Driven Development for regression testing and executable specifications.

ATDD should be defined in Sprint Refinement e.g. within a “3 Amigos” session especially on tricky US.

Pairwise Testing[]

A combinatorial method of software testing that, for each pair of input parameters to a system (typically, a software algorithm), tests all possible discrete combinations of those parameters.

TDD with tiny steps[]

Start developing Unit Tests with tiny little steps. Add only a little code in test before writing the required production code. Then repeat. Add only one Assert per step.


Automated unit tests must be

  • Fast: in order to be executed often
  • Isolated: No dependency between tests.
  • Repeatable: No assumed initial state, nothing left behind
  • Self-Validating: No interpretation or intervention.
  • Timely: Tests are written at the right time (TDD, DDT, Plain old Unit Tests - POUT)

Defect Driven Testing - DDT[]

This happens whenever a case was not addressed in a unit test, then you should  write a unit test that reproduces the defect – Fix code – Test will succeed – Defect will never come back

Using Code Coverage as a Goal[]

Use code coverage to find missing tests but don’t use it as a driving tool. Otherwise, the result could be tests that increase code coverage but not certainty. Code coverage is much weaker than Branch cov., Decision cov. (see Pairwise Testing) or Path cov. (that late one is usually impossible). Coverture should be adapted with failure impacts severity.

Incorrect Behavior at Boundaries[]

Always unit test boundaries. Do not assume behavior. Parameters may have boundaries from business (require them from the Product Owner) values and also from code (e.g. 0-255 for a byte). Intervals between boundaries should be tested on valid AND invalid intervals. Look for “Pairwise testing” when facing too many combinations.

Excessive Mock usage[]

When unit testing, dependencies must be faked to isolate behaviors. If your test needs a lot of Test Doubles (mocks, stubs, fakes...), then consider splitting the testee into several classes or provide an additional abstraction between your testee and its dependencies.

Coding Family[]


This family gathers practices directly related to coding habits, the Coding Guidelines being the most basic pattern that every Dev should comply to.

Naming is a process[]

The easiest approach I’ve yet found for finding good names is to progress along a series of regular steps. The steps a name goes through are:

  • 1- Missing
  • 2- Nonsense
  • 3- Honest
  • 4- Honest and Complete
  • 5- Does the Right Thing
  • 6- Intent
  • 7- Domain Abstraction

I want to learn more about this...


Knowing code smells[]

“Code smell, also known as bad smell, in computer programming code, refers to any symptom in the source code of a program that possibly indicates a deeper problem”. A Code smell deserves a refactoring to remove it.  Each code smell has a subset of applicable refactoring techniques.

Fail Fast[]

Exceptions should be thrown as early as possible after detecting an exceptional case (e.g. undefined behavior or invalid values). This helps to pinpoint the exact location of the problem by looking at the stack trace of the exception. An Error Handler service could also be triggered to track the exception with value and calling object or service.

Do stuff or know others, but not both[]

It is a simple approach to Domain Driver Design (DDD) tactical patterns. The role of the tactical patterns in DDD is to manage complexity and ensure clarity of behavior within the domain model.

·       I want to learn more about this...

Package Cohesion[]

  • Release Reuse Equivalency Principle (RREP): The granule of reuse is the granule of release.
  • Common Reuse Principle (CRP): Classes that are used together are packaged together.
  • Common Closure Principle (CCP): Classes that change together are packaged together.

Data Class[]

A data class refers to a class that contains only fields and crude methods for accessing them (getters and setters). These are simply containers for data used by other classes. These classes do not contain any additional functionality and cannot independently operate on the data that they own.


The software is difficult to change. A small change causes a cascade of subsequent changes.

Magic Numbers / Strings[]

Replace Magic Numbers and Strings with named constants to give them a meaningful name when meaning cannot be derived from the value itself.

Mindset Family[]


In the CCC approach, mindset is key because the code is to be refactored over and over again along with detected smells removal. CCC promotes an "Egoless programming" to ease collective ownership of the code.

Moreover, it also appears that Devs bear an implicit burden which is the code responsibility. Uncle Bob kind-of demonstrates that one day or another code will kill because it can be found everywhere; therefore, if as Developers we don't take the initiative on that, we marginalized or even blacklisted and treated as irresponsible, hence the craftsmanship mindset.

Uncle Bob’s Programmer’s Oath[]

  • 1-I will not produce harmful code.
  • 2-The code that I produce will always be my best work.
  • 3-I will not knowingly allow code that is defective either in behavior or structure to accumulate.
  • 4-I will produce, with each release, a quick, sure, and repeatable proof that every element of the code works as it should. I will make frequent, small, releases so that I do not impede the progress of others.
  • 5-I will fearlessly and relentlessly improve my creations at every opportunity. I will never degrade them.
  • 6-I will do all that I can to keep the productivity of myself, and others, as high as possible.
  • 7-I will do nothing that decreases that productivity. I will continuously ensure that others can cover for me, and that I can cover for them.
  • 8-I will produce estimates that are honest both in magnitude and precision. I will not make promises without certainty.
  • 9-I will never stop learning and improving my craft

Uncle Bob's original post on his blog in 2015:

Watch him presenting it at GOTO17:


GOTO 2017 • The Scribe's Oath • Robert "Uncle Bob" Martin


Issues found today come from solutions found yesterday so don’t blame bad solutions. Fix what needs to be fixed and try to improve legacy as much as possible. Good Samaritan and comprehension provide the proper collaborative environment for a Team

Continuous Learning Process[]

As a “Knowledge Worker”, continuing innovation is part of your work. This is your responsibility. You also need to develop a proper environment (attending dojos, reading books, …) and unlock your intrinsic motivation.

Boy Scout Rule[]

«There are 2 things a boy scout leaves behind him: nothing and “thank you” » It means leaving the campground cleaner than you found it; it does not need to be perfect but at least the cumulated efforts, even the smallest, will make the place nicer!

Keep it Simple, Stupid (KISS)[]

Simpler is always better. Reduce complexity as much as possible. This often goes along with YAGNI (You Ain’t Gonna Need It).


If you do something a certain way, do all similar things in the same way: same variable name for same concepts, same naming pattern for corresponding concepts.

Violate the principle of Least Astonishment[]

If a component of a system should behave in a way that most users will expect it to behave; the behavior and structure should not astonish or surprise users.

Being Arbitrary[]

Have a reason for the way you structure your code, and make sure that reason is communicated by the structure of the code. If a structure appears arbitrary, others will feel empowered to change it.

Refactoring Family[]


This family exposes some patterns and anti-patterns related to the refactoring activity.

It is Easy to Remove[]

We normally build software by adding, extending or changing features. However, removing elements is important so that the overall design can be kept as simple as possible. When a block gets too complicated, it has to be removed and replaced with one or more simpler blocks.

Small Refactoring's[]

Only refactor in small steps with working code in-between so that you can keep all loose ends in your head. Otherwise, defects sneak in and data migration becomes tremendous.

Migrate Data[]

Move from one representation to another by temporary duplication of data structures. Consider small and frequent refactoring rather than wide range refactoring area for data migration could also be tremendous!

The Three Laws of TDD[]

  • 1-You are not allowed to write any production code unless it is to make a failing unit test pass.
  • 2-You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  • 3-You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

Always have a Running System[]

Change your system in small steps, from a running state to a running state. Isolation of the area to refactor is key, so prepare fakes, TDDs and possible new interfaces at refactoring boundaries before reengineering.

Needless Complexity[]

The design contains elements that are currently not useful. The added complexity makes the code harder to comprehend. Therefore, extending and changing the code results in higher effort than necessary.


Software code (unit tests included) is difficult to change. A small change causes a cascade of subsequent changes.


Code contains duplication or design duplicates (doing the same thing in a different way). Making a change to a duplicated piece of code is more expensive and more error-prone. Eliminate duplication. Violation of the “Don’t repeat yourself” (DRY) principle.

SOLID Family[]


I want to learn more about this...


Single responsibility principle (SRP)[]

·        A class should have one, and only one, reason to change.

Associated smells: Large Class (more than 30 methods) / Duplicated Code / "Shotgun surgery" to change application / Divergent Change (the class changes more frequently than other classes in the application)

Open–closed principle (OCP)[]

·        Software entities should be open for extension but closed for modification.

You should be able to extend a classes behavior, without modifying it.

You should not alter an existing API behavior but rather extending the component with new APIs.

The class needs to change for more than one reason.

Liskov substitution principle (LSP)[]

Functions that use references to base classes must be able to use objects of derived classes without knowing it.

Associated smells: explicit casting / You are not using the base class without knowledge of the derived classes / Preconditions cannot be strengthened in a subtype / Postconditions cannot be weakened in a subtype.

Interface segregation principle (ISP)[]

Many client specific interfaces are better than one general purpose interface.  Some code that violates this principle will be easy to identify due to having interfaces with a lot of methods on.  This principle compliments SRP, as you may see that an interface with many methods is actually responsible for more than one area of functionality.

Dependency inversion principle (DIP)[]

Depend on abstractions (module or duck type), not on concretions (class).

Do not depend on things that change less often than you do.

Shotgun surgery[]

Making any modifications requires that you make many small changes to many different classes.

I want to learn more about this...

Abrupt shared API Change[]

Changing the behavior of an API or its signature without a decommissioning policy (such as deprecation notice with some delay or use measurement before being removed) will generate a lot of debugging efforts waste of time on the client side

Feature Envy[]

A method accesses the data of another object more than its own data. This smell may occur after fields are moved to a "data class". If this is the case, you may want to move the operations on data to this class as well.

I want to learn more about this...

Extra Usages[]

If you have any idea that would renew the gameplay, share your experience! :)

"Get Rid of Foes"[]

  • distribute all family cards (power card included) between players
  • the player to the left of the one who distributed must pick a card from the distributer
  • the player must get rid of a card on a stack without showing it but he tells the family and name of the card
    • if any colleague suspects the player lied, the colleague turns the latest card at the top of the stack
    • if the player lied, he gets the 3 latest cards
    • if the player did not lied, the colleague gets 3 latest cards
    • if the power card is turned, the colleague takes 6 cards
    • if the power card is owned, it can be used to cancel the stack punishment - the power card is then removed from the game
  • the player turns to the left neighbor who will draw a card from his hand
  • the process is repeated until a player got rid of all his cards, each player reveals the Foes in hand, each Foes scores +1 to the player score - the lowest score wins

Jeopardy my craftsmanship[]

  • a player is drawing a card from the card set, he tells the definition, the colleagues must tell the card name
  • if someone guessed correctly, he owns the card
  • otherwise, the name is said, and the card is put randomly in the card set
  • the colleague to the left of the player now draws a card to continue the game
  • at the end, the winner is the player who owns more cards

Hanabi for CCC[]

Original rules :

Adaptation to Happy Family - original rules[]

  • each family already has a color
  • each card has a number
  • to play hanabi as is: just remove extra cards to match the rules + select any object around you to match tokens

Adaptation to Happy Family - CCC way[]

  • the aim is to clean each player's card set
  • foes can be removed with relatives
  • the player looks into someone else's card to spot foes or relatives just like he would do a code review
  • the number of token illustrates the amount of available story points / workload that would be dedicated to technical debt

Extra flavours[]

Usage # 1 - Happy family mode[]

alternative rules such as 

  • Card description could be read aloud to share the content
  • Play around description to learn more: Ask a counter question to get the card
  • Card description could be read aloud to share the content

In any usage[]

A subset could be used from

  • a random selection
  • relatives or foes
  • grades
  • team relevance
  • ...