Constraints in General
A constraint, also known as an activity, is an artificial challenge during an exercise, e.g. code kata, coding dojo or Coderetreat. It is designed to help participants think about writing code differently than they would otherwise. Every activity has a specific learning goal in mind.
Constraints are the primary tool to focus a coding exercise. For example, to improve my Object Orientation, I will practise Jeff Bay's Object Calisthenics or even Brutal Coding Constraints. Some constraints are an exaggeration of a fundamental rule of clean code or object oriented design and might be applicable during day to day work. More extreme ones will still help you understand the underlying concepts.
Learning Goal
Verbs instead of Nouns is listed as stretch activity. Stretch activities are designed to push you out of your usual coding habits - your coding comfort zone - and broaden your horizon by showing you new ways how to do things. By design stretch activities might look awkward, ridiculous or even plain wrong.
The learning goal of Verbs instead of Nouns is to push you out of noun oriented thinking. Noun oriented thinking is a way of object orientation, where the nouns of the problem description become classes, and the verbs become methods. This is the classic definition of Object Oriented Analysis and Design. As with any technique, following it blindly is not healthy. According to Alan Kay Object Oriented Programming is about messaging and encapsulation. He wanted "to get rid of data". His objects are defined by the messages they accept. Object orientated programming becomes verb based, if we focus on behaviour.
In functional programming, verbs are natural. All activities are functions. For example Steve Yegge describes functional programming as verb based in his humorous critique of 2006's style Java. Verbs instead of Nouns is an object oriented constraint.
Interpretation of the Constraint
Besides its name there is no information about this constraint available on the Coderetreat site. There was a discussion how to meet the constraint (which has been deleted to make space for the new GDCR organisation): Separate value objects from operations and build service objects for the operations, which would be named with a verb. Or do not consider what a class contains or represents, but what it does. This keeps the concerns separated and the classes small and simple.
Being a Value
Obviously not everything can be named with a verb. Values, at least primitive values, are things:
2, true, "Hello"
. The Oxford Dictionary explains value - the way we use it in code - as the numerical amount denoted by an algebraic term; a magnitude, quantity, or number. Now "Hello"
is neither a quantity nor number, it is a constant term. The entry about Value Object on Wikipedia defines a value object as a small object that represents a simple entity whose equality is not based on identity: i.e. two value objects are equal when they have the same value, not necessarily being the same object.. The definition uses "having the same value"... I am not getting anywhere.On the other hand, in the Lambda Calculus, even numbers are represented as functions. For example the number two can be represented by the higher order function
n2(f,x) = f(f(x))
, see Tom Stuart's Programming with Nothing. Being a function makes it verb based but which which verb would name n2(f,x)
?Suitable Exercises
For a stretch exercise, a suitable exercise is challenging. There is no point if everything goes smooth. We need an assignment that does not support the constraint. Everything that is functional in nature is not suitable, because functions are verb based. This rules out algorithmic exercises as algorithms are usually functional. We need a kata with some state - some "values" - and the need to mutate that. Let's try different problems.
Discussion of Game of Life
As I said, I did Verbs instead of Nouns first on the Game of Life. While Game of Life is a larger exercise, most of it can be implemented in a functional way, lending itself to the constraint. Here are some of its classes:
Classify
has two implementations, ClassifyPopulation
and ClassifyReproduction
. Both classes check if a population is optimal for survival or not. There is one public method and its arguments are passed into the constructor. These classes are functors, function objects, the representation of functions in object oriented languages. The class name suits these class and the verb oriented thinking helped in extracting and evolving them.LocateCell
represents the position of the cells in the grid. It contains two integers x, y
and an equals
method to identify same positions. What is the verb of being a coordinate? A coordinate locates, as it discovers the exact place or position of something (Oxford Dictionary). Here Coordinate
might be a more natural name.I am unhappy with
LookupLivingCells
. It has two methods reproduce
and isAlive
. The verb Lookup
only points to the second method. A proper class name should contain all functionality the class offers, so LookupAndTrackLivingCells
is more appropriate. I do not like class names with And in them because they violate the Single Responsibility Principle. On the other hand - in an object oriented way - the class is fine as it encapsulates the collection of LocateCell
s and represents a Generation
of cells.Discussion of Trivia
Next I tried refactoring towards the constraint. Refactoring towards a constraint allows a more fine grained transition. Together with fellow craftsman Johan Martinsson we worked on the Trivia exercise and spent several hours extracting "verbs" from the legacy code base. (Many of the observations I describe later were made by Johan or found through discussion with him.) Let's look at some of the classes we created:
We extracted
Ask
. An noun oriented name might be Questions
or QuestionsDeck
. It is a closure over the list of questions and it does ask them.MovePlayerOnBoard
contains the board of the Trivia game. We felt being unable to escape our mental model of objects as state. On the other hand, the code for the class was chosen only by looking at the behaviour. It must be good. MovePlayerOnBoard
has one public method but is not a functor because it contains mutable state, the positions of the players on the board.Score
is a similar reasonable class by object oriented standard. A player scores by answering correctly, or does not score by answering wrongly. Like MovePlayerOnBoard
and AllowToPlay
, it is a real object with internal, encapsulated state and various methods manipulating its state. These classes are far away from functors and functional programming.Conclusion
Verbs are abstractions, too. There are "small verbs" like
increasePurse
, and higher level ones like moveAndAsk
. Smaller verbs are easier to identify and to create or extract. Most of our verbs encapsulate primitives. If the code is primarily state, finding a suitable verb is hard. These verb names feel even more "wrong" than other verb oriented names. Maybe, when we only behaviour of a class is mutating the subject, we should show the subject in its name.Responsibilities
A method that does much is difficult to name with a single verb. In the refactoring exercise, we moved out logic to make the describing verb(s) simpler, clearer and "pure". During refactoring we had trouble finding concise verbs for convoluted legacy methods. I guess when creating verb based code from scratch, such methods would never exist. Naming classes as verbs helps to split logic into more classes containing different aspects of data.
Design
Many verb oriented classes are functors, objects with a single method. Some are closing over state. There are classes with different aspects of the same verb, e.g.
answerCorrectly
and answerWrongly
in a class Answer
. Despite some weird names, the resulting design was always good. The constraint drives to nice, small, focused objects.Usefulness as Exercise
The constraint is difficult. Especially when dealing with state, it is hard to find verb oriented names. It forces small, focused objects and discourages state oriented designs like Java Beans. Intermediate Object Oriented programmers will gain most of the constraint. They understand the basics of objects and usually create noun based classes. With more knowledge of object oriented design principles like SOLID, the constraint might have has less impact on the design.
Example Code
No comments:
Post a Comment