Tuesday, January 16, 2018

Events are messages that describe state, not behavior

I have felt, for some time now, that the literature explains event sourcing poorly.

The basic plot, that current state is just a left fold over previous behaviors, is fine, so far as it goes.  But it rather assumes that the audience is clear on what "previous behaviors" means.

And I certainly haven't been.

In many, perhaps even most, domain models can be thought of as state machines:

Cargo begins its life cycle when it is booked, and and our delivery document changes state when the cargo is received, and when an itinerary is selected, it gets loaded in port, the itinerary changes, each of these messages arrives and changes the state of the delivery document.

So we can think of the entire process as a state machine; each message from the outside world causes the model to follow a transition edge out of one state node and into another.

If we choose to save the state of the delivery document, so that we can resume work on it later, there are three approaches we might take
  • We could simply save the entire delivery document as is
  • We could save the sequence of messages that we received
  • We could save a sequence of patch documents that describe the differences between states
Event sourcing is the third one.

We call the patches "events", and they have domain specific semantics; but they are fundamentally dumb documents that decouple the representation of state from the model that generated it.

This decoupling is important, because it allows us to change the model without changing the semantics of the persisted representation.

To demonstrate this, let's imaging a simple trade matching application.  Buy and Sell orders come in from different customers, and the model is responsible for pairing them up.  There might be elaborate rules in place for deciding how matches work, but to save the headache of working them out we'll instead focus our attention on a batch of buy and sell orders that can be paired arbitrarily -- the actual selects are going to be determined by the model's internal tie breaker strategy.

So we'll image that a new burst of messages appear, at some new price -- we don't need to worry about any earlier orders.  The burst begins...


After things have settled down, we restart the service. That means that the in memory state is lost, as has to be recovered from what was written to the persistent store. We now get an additional burst of messages.


Using a first in, first out tiebreaker, we would expect to see pairs (A,1), (B,2), (C,3), and (D,4). If we were using a last in, first out tiebreaker, we would presumably see (D,1), (E,2), (C,3), (B,4).

But what happens if, during the shutdown, we switch from FIFO to LIFO? During the first phase, we see (A,1) matched, as before. After that, we should see (D,2), (E,3), (C,4).

In order to achieve that outcome, the model in the second phase needs knowledge of the (A,1) match before the shutdown. But it can only know about that match if there is evidence of the match written to the persistent store. Without that knowledge, the LIFO strategy would expect that (D,1) were already matched, and would in turn produce (C,2), (E, 3), and (A,4). The last of these conflicts with the original (A,1) match. In other words, we're in a corrupted state.

Writing the entire document to the event store works just fine, we read a representation that suggests that A and 1 are unavailable, and the domain model can proceed accordingly. Writing the sequence of patches works, because when we fold the patches together we get the state document. It's only the middle case, where we wrote out representations that implied a particular model, that we got into trouble.

The middle approach is not wrong, by any means. The LMAX architecture worked this way; they would write the input messages to a journal, and in the event of a failure they would recover by starting a copy of the same model. The replacement of the model behavior happened off hours.

Similarly, if you have the list of inputs and the old behavior, you can recover current state in memory, and then write out a representation of that state that will allow a new model to pick up from where the old left off.

Not wrong, but different. One approach or the other might be more suitable for your unique collection of operational constraints.

Monday, January 15, 2018

Command messages in REST

Kevin Swiber, of SIREN fame, just taught me a nifty trick for describing commands to a resource

Background: commands are semantically unsafe operations, as described in the HTTP specification. They are messages that expect to induce a change of state on the server, they invalidate caches, and so on.

In considering a design that conforms to the REST architectural style, it's useful to ask "how did we do it on the web?" We had URI, and HTTP, and HTML; those elements alone were enough to support catastrophic success.

Now, in HTML, the only readily available link for unsafe operations was the form, which supported only GET and POST. When there's only one road, you take it: servers would send HTML representations that would include Forms, that would describe to the client how to create the command message.

Notice that this is very much a hypermedia approach - if the server wishes to communicate that the command should not be sent, it simply removes the form from the representation.  Elements that are no longer necessary can be removed from the form.  New optional elements can be added by simply including a new input control and providing a reasonable default value.

What this teaches us is that a POST message with an application/x-www-form-urlencoded payload is a perfectly satisfactory way of modeling a command sent to a resource.

But I've got to admit,  that doesn't feel much like "REST".

So here's another way of thinking about it.

HTTP Patch affords the modification of resources.  We tend to think about the payload as a list of changes to make; but another way of thinking about it is that the payload describes a list of commands.  For example, application/json-patch+json is a document that describes operations; add, remove, and so on.

First trick: any resource that supports PATCH application/json-patch+json can just as easily provide the same functionality via POST application/json-patch+json.  The semantics of PATCH are more specific than those of POST, but they don't fundamentally conflict with each other.

Second trick: application/json-patch+json is just a representation of a sequence of operations; with those operations taken specifically from the vocabulary of manipulating a json document.  We don't particularly want to be borrowing those semantics unless they happen to be a particularly good fit for our domain; we likely have our own names for operations, particular parameters, and so on. So we instead might choose our own patch document representation; and write it up so that clients can be coded against it.

Third trick: these media types don't have any magical properties; they are just rules for taking semantic meaning and encoding that meaning as bytes, and then reversing the process at the other end. We can use any byte representation we like, provided that the client and the server agree on the rules being used. We could use text/plain, or application/json. Alas, both of those representations suffer from the problem that we need additional out of band communication to ensure that both ends of the conversation understand the meaning the same way.

Fourth trick: if our command message can be represented as a collection of key/value pairs (likely the case, if we account for hierarchical keys), then application/x-www-form-urlencoding is another possible representation that we might use. It shares the same problem we just saw: the client and server need to agree on semantics. But with one important difference: we already possess a standard format with facilities for describing application/x-www-form-urlencoded representations in band: HTML.

So, yeah -- it's REST.

That still doesn't mean "easy"; the client still has to know what it wants to do, how to find the right form to do it, how to find the fields it wants to set before submitting the form.  In much the same way that JSON Patch puts semantics on top of JSON, you need something that describes your domain semantics on top of HTML (or whatever other hypermedia representation you prefer).


An advantage in this approach is that it allows us to take advantage of the cache invalidation semantics of POST; which is to say, because we are sending the message to be handled by "the" resource, as opposed to some other resource that understands the semantics of a specific command, the caches are able to invalidate the representations that are actually being changed, rather than invalidating an irrelevant side channel.


Thursday, January 4, 2018

Property based testing: Mars Rover

My go to TDD exercise has been the mars rover kata.  Trying a property test first approach to it has been a struggle.  Compared with an example driven approach, there seems to be a whole lot of front loaded pain without an obvious payoff.

I reached out to Paul Holser to see if I was missing a bet, and of course the discussion turned to what sorts of properties I had discovered in the design.

First property: for all inputs, the output is an ordered collection of representations of rover positions.  If we are checking within the domain boundary, this is pretty trivial -- we can use the type system to enforce this constraint.  If we are checking from outside of the boundary, then we're checking that the lines of text/bytes that have been returned to us can be parsed; three entries per represe, the first two entries are coordinates/integers, the last entry is a member of the set of cardinal directions.

Second property: for all inputs, the number of representations in the output equals the number of rovers described by the input.  Rovers are conserved.

Third property: for any inputs, you get the same output each time you run it.

Fourth property: for any pair of inputs, reversing the order of execution does not change the outputs.


In other words, its a pure function.  I don't actually know the battery of tests that you should run to establish this fact.

A rover with an empty instruction set remains at the same coordinates in the same orientation.  This gives us our fifth property: for all inputs, if we replace a single rover's instructions with an empty instruction set (thereby creating a different input), the corresponding output will have the same position.  Note that this indirectly demonstrates that the order of the outputs matches the order of the inputs.

This property would not apply if the rovers moved other than by consuming their own instructions. For example, if one rover were to push another rover out of the way, then the property would not hold.

The above identity leads to two additional properties, both variations of different paths, same destination.

The sixth property takes advantage of the identity to allow us to establish that the behavior of the rovers is consistent with their programs being executed in the right order.  So for all inputs, we can select any rover, and create a new program in the following way: the positions an instructions of the rovers before the selection in the list are copied directly, the positions of the remaining rovers are copied with empty instructions.  We get the corresponding output, and then build a second program -- the output positions are taken as inputs, with empty instruction sets assigned to the rovers before the selected rover, and the original instruction sets assigned to the remainder.  The property to be checked is that the output of this second program matches the original that we started with.

The seventh property is similar; instead of breaking up the original program along neat rover boundaries, we can also split the selected rover's instructions into two pieces, running part of the instruction set with the rovers ahead of it, then running the remaining instructions with the subsequent rovers.

Both of these are basically establishing that we're dealing with a stateless process; the next collection of positions depends only on the current collection of positions and the next instruction.

Up until this point, we haven't really been looking at the semantics of the output at all; we've got a list of coordinates and orientations, but all we've done is check for equality.

Putting this another way, the simplest thing that could possibly work is still to ignore the instruction sets entirely, and simply return the original positions and orientations in each case.

The plateau is rectangular, and presumably the boundary effects are equivalent on all sides.  If you flip the rectangle upside down -- exchanging north for south and east for west -- you get the same configuration of rovers in a different coordinate system.   Right and Left have the same effect on orientation that they did before the flip.  Any interactions with the boundary will still appear at the same points in the evaluations of the rovers.

This yields our eighth property: for any input, if we flip the input position, compute the output, and then flip the output, we should get the same answer that we would get from running the original output as is.

There is a similar result for quarter rotations, if you adjust the input so that the plateau itself is square.

Rotations are mostly immune to boundary effects and collisions, so it's probably reasonable to start there.

One assumption that we probably need to make is that all valid inputs have rovers that start within the region of the specified plateau.  The problem statement doesn't address that point.  I don't think property based testing helps much here - running the checks can only tell you if the test and implementation made compatible assumptions, not correct assumptions.

Property nine: for all inputs, we can select any rover and replace it's original instruction set with one that has all of the move instructions removed.  When we run this program:
  • The coordinates of the output should match those of the input
  • The orientation of the output will match that of the input if, and only if, the difference in the count of left instructions and the count of right instructions is a multiple of four. 
Finally, we have the possibility of an input that forces us to change the position of the rover!

This establishes that we've got four-symmetry, that left and right cancel each other out, and that rotations preserve position.

Property ten: for all inputs, we can select any rover and replace it's original instruction set with a one that elides all of the left and right instructions.  When we run this program, the orientation of the selected rover will be unchanged.

EDIT: come to think of it, any single instruction leaves at least two of the three properties unchanged; the remaining property changes by at most one unit.  The complication of the move instruction is that you need the orientation to know which property is changing in which direction.

We can introduce into this domain the concept of a displacement - we're in a taxicab geometry.  The number of moves in an instruction set establishes an upper bound on the displacement that can be achieved; we know that the rover will be found somewhere in the circle.

Property eleven: for all inputs, we can measure the displacement of the output coordinates from the input coordinates.  For each rover, the displacement will be less than or equal to the count of moves in its instruction set.

Furthermore, if the circle doesn't reach the boundary of the plateau, then we don't need to worry about boundary effects for that rover.  Taking the initial positions of the rovers, and the size of the bounding circles allows us to compute a bounding box; if the box doesn't reach the plateau boundaries, then the simulation is completely free of boundary effects.

If the plateau is large enough to enclose the bounding box at two different locations, then we can establish twelfth property - that of translation symmetry in the following way.  Given any valid input, we can compute the extents of a bounding box that encloses the possible programs of all rovers.  Choose a displacement in positive x and y.  Compute the dimensions of a plateau by adding the displacement to the extent of the bounding box.  Create two inputs using this plateau: for the first, compute the initial positions of the rovers such that the lower left corner of the bounding box is at the origin; for the second, compute initial positions of the rovers such that the upper right corner of the bounding box is at the upper right corner of the plateau.  Note that the relative displacment of the input coordinates of the corresponding rovers should be the same.  Compute outputs for both programs; the displacements of the corresponding outputs should all match.

The thirteenth property also plays with bounding boxes to establish this property - that if the bounding circles of two rovers don't overlap, then they don't have any interference effects.  The check goes something like this: first you run a single program with all of the rovers participating.  Then you run a program that isolates each rover on the same plateau, and confirm that the final positions of the isolated rovers matches that predicted by the single program containing all of the rovers.

It's not clear how you transform input with overlapping bounding circles into one that doesn't have them.  Do you move the rovers? shrink the bounding circles? skip examples that don't match the criteria?

But in the main, it seems to be a very powerful pattern to use an input as a seed from which you can compute an input that has the properties you want to verify -- using an identity transformation wherever possible.

It's not so clear to me that these constraints are driving the design in any useful way.  For example, we don't have any properties that establish that left and right are correctly oriented.  We don't have any tests that actually demonstrate that the rover has moved.





Tuesday, January 2, 2018

Property based testing: thoughts of a novice.




The tension between these two ideas drives me nuts.  Thinking way harder means that I'm not delivering features faster.

Example based testing is straight forward; choose an input, hard code the output, remove the duplication, repeat until you have no more examples that produce the wrong output.  You may even be able to estimate the minimum required number of tests just by thinking about the cyclomatic complexity of the problem.

But this in turn means that you can't easily judge "complete" just from looking at the demonstrated examples.  As Scott Wlaschin points out, a finite suite of example tests can be beaten by a pathological implementation that is fitted to the suite.

Property based tests handle this concern better -- they explore the domain, rather than just sampling it.  That's a lie, of course; what property based tests are really doing is sampling a lot of the domain -- enough that the pathological fake is more expensive than just solving the problem.

My most startling test result, ever, came about from a property test which revealed that I had completely failed to recognize that the properties that I thought would hold were not consistent with the implementation I had chosen.

But it didn't come from randomly exploring the space, but rather choosing an example from the domain that I recognized was "weird".  Fortunately, there were lots of weird values in the domain, and they all demonstrated that my implementation didn't support the property in question.  So I got
"lucky" without having to write four billion tests.

I'm not at all sold on the idea of using a random input generator to find a needle in the haystack.


Friday, December 22, 2017

Injection: a refactoring exercise.

Yesterday, I needed to extend a program that had a broken design.

The existing program works fine; but it has hard wired into it an identifier for a specific database host.  That host name is used during execution to create the URL string that is passed to JDBC, by merging the hard coded host with a configured database name.

An additional constraint is that I need to have the old and new versions of the program running in parallel, in the same environment.  We're going to run the two reports in parallel for a time, and then decommission the legacy.

So, how to dig my way out?  Here's the outline of how I did it....

As is often the case, I rely on Parnas -- the legacy implementation is the result of a decision that I want to change. Therefore, I begin by creating a boundary around that decision.

In this case, the code in question was computing a new string from the hard coded literal and a member variable.  So I applied an "extract method" refactoring to give me a member function that promised to provide the string that I needed.  The method simply returned the calculated string, as before.

I then created a new type; the configuration model already included DatabaseName as an explicit concept,  but it didn't have an understanding for the URL.  So I introduced a DatabaseUrl type, that was simply an alias for a string.

I then inserted that type into the middle of the method -- so we compute the string, use the string to create a new DatabaseUrl, then use the DatabaseUrl to yield the string to return.

Next, I apply extract method again, creating a function that would convert the DatabaseName to the DatabaseUrl.

Next, I take DatabaseUrl, which had been a local variable, and make it a private member of the object; it now has the same lifetime and scope as DatabaseName, the only different is that it is being initialized at a different point in the program.

Next, I copy the logic to initialize the DatabaseURL to the method where the DatabaseName was initialized.  I now have a redundant copy, which I can remove -- the query that produces the string representation of the url when I need it is just a toString() on the member value

At this point, the only place where the DatabaseName is used in in the initializer, so I can demote that to a local variable in the method, and inline it away.

I don't think we should be using the old method on the API any more, so I mark it as deprecated.

Reviewing at this point -- through a sequence of refactorings, I've managed to extend the existing API, adding the new method I need to it, while at the same time ensure that my existing tests are exercising that code (because the implementation of the old API feeds into the new one).

The legacy implementation includes a factory, which when passed the configuration (captured within a Properties object) returns the interpreted configuration.  So the new piece I need is a factory with the same signature, that understands the new configuration.

But before I can think about creating a new factory implementation, I have to address a second problem -- I was sloppy ensuring the integrity of the composition root.  The factory I need to replace is allocated behind two different default constructors.

So I need to perform a second round  of refactoring.  The member variable for the factory that I need to replace is too specific, as it names the implementation directly.  So the spelling of that type needs to be changed to the interface.  Fortunately, the interface I need is already available, so I can just replace it.

Then we delete the assignment at the member variable declaration.  At this point, everything goes red, because we aren't assigning a final field.  Next, we fix the compilation problem by allocating a new instance of the factory in the constructor body.

Next, we work our way back up the stack to the composition root.  There are a couple possibilities; you can either develop a completely new path from the root to the assignment so that the factory can be passed along, and then with everything wired up remove the duplication, or you can create new signatures, but play criss cross -- the existing implementation gets a new signature, and a new method appears which creates a default factory and then routes to the real implementation. 

I prefer the latter course; you only really need to preserve the signatures that are part of the public API.  Anything that is private to the module you can simply change, watching for local compile errors.

At the end of the game, I have the starting position I'm waiting for: me legacy implementation, with the creation of the default factory at the composition root.

Now I'm ready to make the easy change - implement the new factory, clone the composition root, and replace the legacy factory with the new implementation.

Sunday, November 5, 2017

TDD: Mars Rover

I took some time this weekend to practice the Mars Rover kata again.

My focus in the exercise was duplication - can we proceed from hard coded outputs, and arrive at a viable implementation simply by removing the duplication that must be present?  Of course, the answer is yes -- duplication is duplication; you can remove it any time you like.

I shan't walk through the process here, it should be reasonably straight forward to follow along from the commit history.

With just the one example, I needed almost no investment in the test harness at all; all of my time was spent working in my production code.  Setting aside the one error that forced me to revert, practically all of the work was in the green bar.

My guess is that the process went as smoothly as it did because my previous experiments in the kata act as spike solutions -- I'm not discovering how to achieve the result at the same time that I'm discovering how to remove the duplication.  Removing the duplication is comfortable at each step, because I can see the code evolving towards a design that is already familiar.

This code is tightly coupled to the data representations that we were given for this problem.  Do we need to invest now in the abstractions that would make it easier to change data representations later?  YAGNI says, no, not really; and that's certainly true for a kata in a limited time box.  Make the next change easy is much easier after you know what the next change is going to be.

Kent Beck talked a bit about this in his discussion of triangulation
Triangulation feels funny to me.  I use it only when I am completely unsure of how to refactor.  If I can see how to eliminate duplication between code and tests and create the general solution, then I just do it.  Why would I need to write another test to give me permission to write what I probably could have written in the first place.
Smaller bites makes sense, I think, when the way forward isn't clear.  But the Feynman algorithm also works. So what does that teach us?

Horses, of courses; but I find that answer unsatisfying.

I think it's closer to true to recognize that the tests aren't driving anything; they are instruments that measure whether or not our current implementation is satisfactory over some range of examples.  In particular, they can give us awareness of whether a change we've made has certain classes of unintended side effects.  They inform us, a little bit, about a possible interface.

With the instrumentation in place, we apply changes to the code in increments; not for the design, but because the short feedback cycle makes it easier to localize the errors we introduce along the way.

There are quite a few kata that progress toward a single implementation in increments, what I've come to think of as extending a particular set of requirements.  I think we need more examples of a different sort, where we have to make something new of code originally written for another purpose.

Sunday, October 29, 2017

Aggregate Semantics

First, we need an abstraction for encapsulating references within the model.
This past week, I had a brief, on-line discussion with Yves Reynhout about repositories.  He pointed out that there is a difference between persistence oriented repositories and collection oriented repositories.

A REPOSITORY represents all objects of a certain type as a conceptual set.  It acts like a collection....
(Repositories) present clients with a simple model for obtaining persistent objects and managing their life cycle.
The invocation of the repository might be as simple as



The key insight is that this is just a semantic; behind the interface, the domain model is free to choose its implementation.



We're not really -- at least, not necessarily -- "invoking a method on an entity in the model".  What we are actually doing in this design is capturing two key pieces of information

  • Which document in our data model are we trying to modify
  • Which behavior in our domain model are we modifying that document with
In the usual pattern, the underlying implementation usually looks like "an object"; we acquire some state from the data store, wrap it with domain methods, let the application invoke one, extract the state back out of the object, and write it to the store.

This pattern bothered me for a long time -- we shouldn't "need" getters and setters on the domain objects, yet somehow we need to get the current state into and out of them.  Furthermore, we've got this weird two phase commit thing going on, where we are mutating an entity in memory and the book of record.

A different analogy to consider when updating the model is the idea that we are taking a command -- sent to the domain model -- and transforming it into a command sent to the data.  In other words, we pass the behavior that we want to the data model, saying "update your state according to these business rules".

Tell, don't ask.