Motivation
As it stands right my company has forked the Views Datasource module because it's current architecture is not flexible enough to allow implementers to override all or some of it's field output.
Problem
Currently Views Datasource is hardcoded to use the the default Field API formatters that come with each field. I've spent enough time researching this issue and talking to the likes of @merlinofchaos (he must hate me at this point) to conclude that the problem is not in Core or Views itself. Both provide the appropriate infrastructure to completely customize the Field API rendering experience from within Views. The way that Views allows us to customize the field rendering experience is via the use of Views Plugins.
The problem with Views Datasource is that it implements Views plugins strictly via OOP inheritance. While that is perfectly O.K. if no one ever wished to override this module's behavior, it doesn't work once you need to say something like: "render me all the fields, regardless if they are empty or not", or things like "allow HTML in the title field, because that's what my manager requested". To further complicate matters, if you implement your own Views plugin, there's no clear way of telling Views Datasource: "hey, use my Views plugin!". In other words, without extensive patching or forking, there seems to be no elegant way to tame Views Datasource.
Solution
The architectural changes that I am developing aim to:
1) Provide a default algorithm for rendering fields, while allowing developers to define additional rendering algorithms and substitute our implementation with theirs. I'm considering deploying the GoF Strategy pattern for encapsulating the rendering algorithm classes. In this case the JSON plugin would provide three interchangeable rendering strategies based on the existing ones: SimpleStrategy, SimileStrategy, JqGridStrategy. Other Views Datasource will plugins will provide their rendering strategies as well. I will provide an interface to help developers define their own strategy, and a method that allows them to set their strategy as the default. The Strategy classes will be responsible for handling the rendering of Views rows.
2) Give developers the ability to override the plugin behavior. While row rendering algorithms will be encapsulated by Strategy classes, most likely I'll deploy the GoF Template Method pattern in order to provide some View-wide default behavior that can be overridden by implementers. The main difference between Template and Strategy in this case is that the Template pattern will be performing some basic operations (the "template method") that will not be possible to be overridden, while still allowing developers to define and use their own Views Datasource plugin classes, override rendering flow and modify View-wide aspects that I deem non-immutable.
3) Reduce the amount of duplicated code that currently exists between our Views plugins. This benefit will come as side-effect from "favoring composition over inheritance" when restructuring our class architecture.
4) Ease the process of adding new, or altering existing Views Datasource plugins and formats. By pooling shared behavior into composite classes, and exposing simplistic, nimble interfaces to third-party developers, we reduce the amount of code that has to be written for new plugins and formats.
Dependencies
Part of the rationalle behind this architectural change is the amount of feature requests from Views Datasource users that otherwise would not be possible. Please refer to issue #1623606: Views Datasource 2.x branch, where most of these requests are being tracked for QA purposes. Some of these requests have been marked as duplicate, meaning that they expected to be fixed automatically by the restructuring; other as postponed, meaning that they will need to be revisited on this issue is complete.
Addendum:
Why the Strategy pattern fits us?
One of the drawbacks of the Strategy pattern is that the client must be fully aware of the strategy. In our case the "client" is the Views UI, and the good news is that Views is already aware of the Strategy (rendering), because the Views UI explicitly specifies the rendering strategy [image stub]. So instead of client strategy awareness being a drawback for us, it ends fitting our use case like a glove.
The Template Method pattern implementation
At some point we must stop sub-classing Views plugin classes like if they where cloned sheep (or lab mice, for that matter). Inheritance is great when you have only one plugin, or two at must, but we have four plugins (without counting the test one). That means we have four places where code is getting duplicated, and four places where code needs to be refactored when we alter the Views Datasource API. This creates a maintenance problem and hinders improvements to an otherwise great module. A good dose of object composition will soothe these ailments.
The Template Method defines a generic abstract class that contains the code to be shared amongst Views Datasource Views plugins. Concrete Views Datasource plugin subclasses will inherit functionality that cannot be overridden, and will be forced to define subclass-specific behavior. A "concrete" method at the abstract class (probably marked as final) will provide the shared plugin functionality. Abstract methods will indicate what operations other plugins will need to implement. The brilliance of the Template Method is that it will allow us to dictate the immutable flow of the application, while allowing others to modify the parts of the flow that matters to them, mainly formatting and rendering flow.
Where is the new code?
Because of the sheer size of these changes, I will be posting my commits to my views_datasource sandbox. Currently my work is still under progress under the rvda-personal sandbox branch. Once my work is completed there I will commit my changes back to the 2.x branch of the official views datasource. This means that this issue (#1699368) will no longer be part of the #VDS-A tag, since it will not be part of the 7.x-alpha release.
Branching strategy
The following branching information applies to the views_datasource sandbox only.
- rvda - Rewrite Views Datasource Architecture branch, stores changes specific to this issue, branched from vds-a. Once major work on this branch is complete, it will be renamed to 7.x-2.x.
- vds-a - Alpha release branch, and rvda's parent. Originally rvda was going to get merged into here (as part of the 7.x-alpha release), but not anymore. This branch will be eventually removed from the sandbox.
- 7.x-1.x - Clean branch mirroring the 7.x-1.x on the original project. Originally the rvda branch was going to get merged back into 7.x-1.x, but not anymore.
- master - Currently contains a backup of my latest code, not to be synced with the real master, please ignore.
Comments
Comment #0.0
Alexander Allen CreditAttribution: Alexander Allen commentedcosmetics
Comment #1
Alexander Allen CreditAttribution: Alexander Allen commentedTagged with API change.
Comment #2
Alexander Allen CreditAttribution: Alexander Allen commentedChanged tags.
Comment #2.0
Alexander Allen CreditAttribution: Alexander Allen commentedCostmeticsss...
Comment #3
Alexander Allen CreditAttribution: Alexander Allen commentedAll commits related to #1699368: #RVDA: Rewrite Views Datasource's Architecture will now incorporate the #RVDA tag in the commit message.
Comment #4
Alexander Allen CreditAttribution: Alexander Allen commentedComment #5
Alexander Allen CreditAttribution: Alexander Allen commentedI think the #VDS-A sits better at the tag field, plus eliminating clutter at the title field ;)
Comment #5.0
Alexander Allen CreditAttribution: Alexander Allen commentedTracking/tagging information.
Comment #5.1
Alexander Allen CreditAttribution: Alexander Allen commentedJust in case....just in case...
Comment #5.2
Alexander Allen CreditAttribution: Alexander Allen commentedsemantics....
Comment #6
Alexander Allen CreditAttribution: Alexander Allen commentedBumped priority, the whole issue queue is basically hostage to #RVDA ;)
Comment #6.0
Alexander Allen CreditAttribution: Alexander Allen commentedmore semantics.
Comment #6.1
Alexander Allen CreditAttribution: Alexander Allen commentedAdd branching strategy section.
Comment #7
Pasquallewould you like to create an official 7.x-2.x branch and continue the work there?
Comment #7.0
Pasqualleedit
Comment #8
Alexander Allen CreditAttribution: Alexander Allen commentedI think that it makes sense, and I've edited some of the description above to reflect that. We will however need to re-tag #1623606: Views Datasource 2.x branch and related issues from #VDS-A to 2.x. #RVDA could stay in place since it indicates what issues require a major change to the module's architecture.
I've re-tagged this issue from #VDS-A to 2.x.
Comment #9
SeanBannister CreditAttribution: SeanBannister commentedWas just going through the issue queue and noticed that a lot of the features I require are dependant on the re-write, I realise not much has happened on the re-write recently in the repo, and I was just wondering if you could give us a progress report on where things are at? Thanks for your work on this.
Comment #10
Crell CreditAttribution: Crell commentedAlso note that this module may become redundant in Drupal 8 almost entirely if #1819760: Add a REST export display plugin and serializer integration. goes to its logical conclusion.
Comment #11
laughnansubscribe
Comment #12
colan@laughnan: "subscribe"-type comments are no longer necessary. Instead, click on the "Follow" button at the top of the issue.
Comment #12.0
colanupdate branching information regarding 2.x branch
Comment #13
rooby CreditAttribution: rooby commentedWhat is the status of the sandbox and the upcoming views datasource 2.x branch?
Comment #14
esolitosHi, I'm just wondering is there's an ETA for this since it's now somewhat two years since this thread started.
In the meanwhile, thanks for the good work! :)
Comment #15
Crell CreditAttribution: Crell at Palantir.net commentedDid this happen, or is it no longer relevant, or...?
Comment #16
ZeiP CreditAttribution: ZeiP as a volunteer commented