Previous to 2.5 came 2.2. But to highlight that changes between the two versions are pretty “dramatic” I chose to bump the version number. Fear not, not everything has been turned upside down.
Everyone hate breaking changes.
- Fellow developers hate them because they make their working applications stop working when the library is updated
- Users hate them because it takes time for their application to be updated with “the next killer feature” and the developer is busy changing a bunch of broken unit tests
- Business people hate them because they cost money and precious development hours
- Author developers hate them because it is a sign that they did not thought the API through enough
But we cannot live in a world of infinite stability or being Microsoft to put up with rotten APIs. Environmental forces change and an author of a software library has one of three options:
- do not break it, even though we all know we were wrong
- offer an alternative API with the new design while we slowly deprecate the previous one
- suck it and assume you were wrong before (and risk being wrong again)
With NMoneys we have the luxury of not having a massive user base. Besides, our users are great fellows that understand that there are breaking changes and Breaking Changes (note the capitals).
The breaking change we are talking about could be one of the worst: changing an interface. A change like that usually means breaking custom implementations of that interface. A royal pain in the neck for the developers that took the steps to implement it.
In our case it is an extension point interface, meaning that we have provided some default canonical implementations of that interface, but allowing injection of custom behavior when that was needed. I chose to believe that there are not a lot of custom implementations of that interface lying around.
Furthermore, an interface change could mean than not only implementations break, but consumers of that interface might break as well (depending on whether the change affects interface’s return types).
In that extent, I choose to believe me lucky as well, for the damage is minimized by returning a type that somehow extends the previous return type (cursive extends as they are not substitutable, from inheritance point of view, only that the way of interacting with the type is pretty much the same).
Alright, enough justification, what is that breaking change everyone talks about?
|version 2.2||version 2.5|
Split allocation return type
In 2.2, a feature to calculate split allocations was added (
Money.Allocate(int)). It returned an array of
Money to represent the quantity allocated to each recipient. It turns out that using a primitive type (and array) is not enough (how many times have seen this?) to represent several situations, for instance: a quantity so small that cannot be allocated; or a quantity that can be evenly allocated, but it has some remainder that is itself too small to be distributed.
The solution is return something that can be used like an array (can be enumerated, indexed and its length interrogated), but communicates more information about the result of the allocation operation:
And the interface change we talked about before is
IRemainderAllocator. As I mentioned before, I do not expect many custom implementations of that interface; but comparing both signatures one has to conclude that we are much better off with the newer version.
Another breaking change is a namespace change. In 2.2 we only had implementations of
IRemainderAllocator and the internal
EvenAllocator, so it made sense to call it .Allocators. With the new features, new types and “surfaced types” it makes so much sense that everything allocation-related “lives” under .Allocations.
But sure a version bump deserves new features on top of breaking changes. And we indeed have more features.
Undoubtedly the star feature of the release are pro-rated allocations. If previously we could allocate a certain quantity amongst n recipients evenly, now we are able to allocate it unevenly, that is, each recipient might get more or less of their even share depending of a ratio (a fraction between 0 and 1) passed to the operations. Such operation could help solve the mildly famous Foemmel’s Conundrum (or how to split 5 cents amongst two parties where the first one gets a 30% and the second the remaining 70%):
But that problem does not have only one solution, as it depends on the order in which remaning quantities are allocated:
Besides try to do complete allocations one can now opt in for incomplete allocations, meaning that one can distribute just the fair amount of a quantity, to discard the remainder if one choses so:
Words of Thank you
Just as I thanked Berryl Hesh for his contribution in 2.2 of split allocation, I have to thank him twice this time: one for the contribution of the pro-rated allocations feature and another one for being patient and assertive when I literally turned his code inside out to simplify the resulting code (I believe) from his contribution. Looking forward for that article.
An extra one comes to show me an interesting way of splitting tests of chunky classes (such as
Money) into partial classes. We will be able to see more of those in further releases.