Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate hydrators into the architecture #12

Closed
Bilge opened this issue Oct 17, 2016 · 7 comments
Closed

Integrate hydrators into the architecture #12

Bilge opened this issue Oct 17, 2016 · 7 comments

Comments

@Bilge
Copy link
Member

Bilge commented Oct 17, 2016

Porter's notion of records is arrays, which are very flexible to pass between interfaces, but once data leaves Porter it is common for applications to want to work with objects instead. The job of a hydrator is to use array data to populate object fields. We should investigate the value of designing a hydrator interface and whether there are any existing hydration libraries fit for purpose.

@RamzesSoft
Copy link

@Bilge
Copy link
Member Author

Bilge commented Nov 1, 2016

DoctrineModule is not suitable because it is both Doctrine specific and Zend Framework specific. Porter requires a general purpose hydration solution.

As an aside, even for Doctrine and Zend Framework users, the hydrator provided by DoctrineModule is incomplete since it does not support embedded documents nor discriminators.

@RamzesSoft
Copy link

i understand, it's just example about how this module can work

@jdreesen
Copy link

jdreesen commented Nov 1, 2016

For the reference: https://github.com/Ocramius/GeneratedHydrator

@Bilge
Copy link
Member Author

Bilge commented Nov 1, 2016

Something like @Ocramius's GeneratedHydrator could be ideal. I haven't used it yet but it looks promising. If it is suitable we still need to decide whether to integrate it directly or create a hydrator interface such that it can be swapped out for something else if the user wishes.

@Bilge
Copy link
Member Author

Bilge commented Jan 31, 2017

If someone wants to attempt hydrator integration, this can now be achieved easily by implementing the Porter 3 Transformer interface and can even be developed as a separate project. In this way we can have as many hydrator transformers as hydrator implementations thus allowing a developer to pick whichever implementation they prefer.

However, after deeper consideration, I now think hydration should not be integrated into Porter at all. Hydrators typically create objects by ignoring the constructor and mutators, forcing potentially invalid state into objects. This is fine when the state is guaranteed to be valid but data coming from a third party cannot usually meet such guarantees. Of course, if there is a hydrator that does invoke an object's constructor and calls its setter methods, this should be fine.

An alternative approach worth consideration is writing a validation transformer before the hydrator to ensure incoming data is valid. Such a transformer would not actually transform the data at all, but rather, simply read the incoming data and throw an exception if it is not compliant.

One final note about hydrators: the interface for Transformer specifies it must return a RecordCollection. Such a collection is defined as a collection of arrays, however a hydrator would violate this by emitting a collection of objects. In principle this is not a problem as long as you can guarantee the hydration transformer is the last in the queue; otherwise it would break all subsequent transformers that expect arrays.

@Bilge
Copy link
Member Author

Bilge commented Mar 11, 2017

After further consideration I do not think it makes any sense to integrate hydration into Porter. This includes strategies whereby the constructor of the object is invoked like normal.

The first problem is Porter::import() returns a RecordCollection, which is an iterator of arrays, and similarly, Porter::importOne() returns an array. Having a hydration transformer at the end of the transformation queue violates this interface by returning an object. However, we could add separate methods for importing hydrated objects.

The second problem is that even if we have another method to import hydrated objects, the best interface we can design for that method is one that returns object, so we still don't know what type of object the call will yield.

For these reasons it is better to leave hydration to the API wrapper class one typically writes to abstract Porter away from the caller. Hydration is therefore not a direct concern of Porter nor even of her plugins (i.e. transformers).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants