Yesterday, I released the new major version of League\Period. While I could go on and talk about what has changed and about the new features introduced. I have chosen instead to talk about the evolution of its Public API. Hopefully this will convey why its public API is the way it is currently and the though and process that goes into adding/improving or removing a feature from a package.
First string representation
Period was first coined as PHP Time Range missing API with a strong opinionated view that its lower bound was included in the range while its upper bond was not.
In version 3.0.0 the
Period::__toString method was introduced. Its goal was to enable a string representation of a Period instance following the ISO8601 representation. To put it simple you could do this
This code was simple and predicable and required no refinement at all.
Adding a new string representation
However, during version 4 cycle the concept of bounds was redefined and from the restrictive view was removed. This meant that the
Period bounds could be explicitly specified by the user. Therefore, we needed a new way to represent a
Period instance as a string that would take into account its bounds. Since ISO8601 does not define such representation I had to look into mathematical representation, and I choose to use the representation described in ISO80000 and in version
4.4.0 along side the introduction of the bounds concept the new
Period::format method was added.
Normalizing string representation
This addition meant that the
Period::__toString was no longer the only way to represent the instance and that
Period::format method could do something
Period::__toString could not, allowing the user to specify the returned format of the date in the string representation. To fill this gap, in version
Period::toIso8601 method was introduced.
Reshaping the feature
What we can infer from version 4 API is that the need for string representation is clear but the expose API seems a bit confusing, which method should I use and when. So for version 5 I tried to have a sane, readable and predictable API following these rules:
- no string representation should be favour above any other one so the
__toStringmethod was removed as its representation was a duplication of the
toIso8601method using its default value.
- to avoid the same pitfall as the
formatmethod was renamed
toIso80000to clarify which representation will be returned by the method.
- a new string representation method
toBourbakibased on the Bourbaki representation was added to complete Interval string representation using internationally recognised interval format.
- And last but not least to complete the feature the following named constructors
fromBourbakiwere introduced to allow converting date interval strings representation to
Which means that in version 5 you can do the following:
Of note the signature of the added named constructors are the same:
- the first argument is the date format expected in the string representation
- the second argument is the actual string representation of a date interval
During development, it was the other way around but I changed it because this way I force the person using the package to never forget about the date format when calling the method since the format
is mandatory and no default value is given. Some will argue that with the introduction of named arguments position does not matter anymore but I believe this to be wrong, if your API requires named parameters to be used then it needs to be improved. Good API should be design to work with positional arguments first, this way it will always work with named parameters.
Last But not least
League\Period is an open source project with a MIT License so contributions are more than welcome and will be fully credited. These contributions can be anything from reporting an issue, requesting or adding missing features or simply improving or correcting some typo on the documentation website.