I am happy to announce the 0.7.3 release of Wikibase DataModel.
Wikibase DataModel is the canonical PHP implementation of the Data Model at the heart of the Wikibase software. It is primarily used by the Wikibase MediaWiki extensions, though has no dependencies whatsoever on these or on MediaWiki itself.
This release contains a new API for working with labels, descriptions and terms, and it deprecates the old API for those.
At the core of the new API is a simple value object representing an until now unnamed domain concept: the part of an Item or a Property that has all those labels, descriptions and terms. The name we gave it is Fingerprint. (Credits and blame for the name go to Lydia :)) The Entity class now has a getFingerprint and a setFingerprint method. Fingerprint itself has getLabels, getDescriptions and getAliases methods. The first two return a TermList, which is made up from Term objects. The later returns an AliasGroupList which consists out of AliasGroup objects.
Why these changes? What was wrong with this approach?
$entity->setLabels( array( 'en' => 'foo', 'de' => 'bar' ) );
The old API is defined by no less than 17 methods in Entity. They add a lot of code to it, contributing to Entity being the highest complexity class in DataModel. That our core (DDD) entity is also our most scary class is obviously not good. Moving the responsibility to a value object inside of Entity is a clean way to tackle this problem, and is also more in line with how the other parts of Entities, such as they list of Claims are handled. On top of the complexity issue, the old API also does badly interface segregation wise. Most code dealing with Terms (ie Labels, Descriptions and Aliases) will not care about all the rest of Entity. Hence it makes no sense to have to feed it an entire Entity object while a Fingerprint or one of its composited in objects would make more sense.
Another important reason to move into this direction is that I want to see Entity go. If you are familiar with the project, this might seem like a quite preposterous statement. Kill Entity? How can I possibly think that is a good idea, and how will the code be able to still work afterwards? In short, Entity tries to unify things that are quite different in a single class hierarchy. The difference between those objects creates creates a lot of weirdness. Entity contains a list of Claim, while Item, one of it’s derivatives, requires a list of Statement, Statement being a derivative of Claim. And not all Entities we foresee will have Claims, Fingerprint, etc. The only thing they will all have is an EntityId, and all we need to facilitate that is a simple HasEntityId interface. All the rest, including the Fingerprint, can be composited in by classes such as Item and Property that implement the appropriate interfaces. Those changes are for the next big release, so if you are using DataModel, it is recommended you switch to using the new Fingerprint API as soon as possible.
And I’m still done with the list – wow. A final reason for the change is that the old API was not only ugly (weird function signatures in places), it was also quite inconsistent in its implementation. It has TODOs in there since the start of the project that state things such as “figure out if we care about duplicates” and “are empty strings valid?”. The new implementation properly takes care of these things, and does no in all cases where it should rather than only in assorted random functions. That those old TODOs remained there for nearly two years go to show how likely it is people “go back to fix it”.
You can do everything you could do with the old implementation with the new one. There are however some things that might be slightly more cumbersome for now, especially in code that is taking in entire Entity objects while only needing a Fingerprint. As we migrate to the new implementation, it will become clear what convince functions will pay for themselves, so those will likely be added in the near future. At the same time several tasks are already easier to do now. The new value objects will also likely provide a good place to put functionality that was oddly places before.
For a list of changes, see the release notes.
And in anticipation of the next release, have some WMDE kittens: