Skip to content

[RFC] Deprecate support for Resource Entity Separation #553

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

Closed
maurei opened this issue Sep 8, 2019 · 8 comments
Closed

[RFC] Deprecate support for Resource Entity Separation #553

maurei opened this issue Sep 8, 2019 · 8 comments

Comments

@maurei
Copy link
Member

maurei commented Sep 8, 2019

I would like to propose to deprecate the Resource Entity Separation feature. This feature allows different models to be used in the service layer and repository layer. See this example project

I propose to deprecate it because of the following reasons

1. It is unfinished
The feature is not well maintained, not documented and not production ready. Even though all tests related to this example project are passing, there are many cases that are not covered and I'm sure many of them will fail (compare with coverage of JsonApiExampleTests). Still, there haven't been any bug reports about this, which probably means this feature isn't used a lot in production. This wouldn't surprise me because there is no documentation about this feature.

2. Usecase is unclear
It is unclear (at least to me) what problem is solved by being able to use a different class in the service layer vs repository layer. There are no indicators about this in the example project because there are no notable difference between the entity and resource model.

The only (incomplete) usecase I can come up with is wanting to have multiple "views" (resources) for one database entity. I am however not sure why allowing for resource entity separation would be the best/only approach to supporting something like this. For example: if the goal is changing the API output depending on authorization, transforming the data can be achieved by leveraging Resource Hooks. Even if there is a valid usecase, I'm still wondering if the extra complexity introduced by the support for resource entity separation outweighs the advantages of keeping ithe codebase simple.

3. Supporting it would greatly postpone time to production readiness
Adding this feature adds a great layer of complexity: every feature needs to be supported for the cases of "normal" usage (non-separated) as well as for usage with resource entity separation. This means that for release of v4, a great deal of work has to be put in in identifying and covering the unsupported use-cases, and new features like Resource Hooks also need to be compatible. The release of v4 would be postponed for a great amount leaving it in a not-production ready state for a longer period of time.

In conclusion
Even if resource entity separation turns out to be useful in certain situations, with the limited development capacity that we have I don't think it is worth maintaining it.

The repository history shows that @roblankey was the main contributor for this feature. I would be grateful to hear your thoughts on this. What was your motivation for this feature?

Any thoughts are welcome.

@wisepotato
Copy link
Contributor

Looking forward to v4 I would imagine a less complex and more robust build is desirable

@roblankey
Copy link
Contributor

Sorry folks, been a little bit since I've monitored this issues here. Thanks for reaching out on LinkedIn to let me know @maurei .

The primary driving factor for the Entity/Resource split is that Entity models are occasionally, if not often, different from Resource models in a service design. It allows a separation of concerns, hidden/remapped components, many-to-many relationship conversation (since that doesn't exist in the JSON-API spec), and potential security separation. I haven't updated the library in a while on my code base, so unfortunately, I'm not certain if there are issues with it now. I haven't been actively updating it either.

On the other hand, it does add a significant layer of complexity, so removing it would definitely simplify things. And since everything is in Git, if it ever came back up, it would be something that could theoretically be pulled back in or forked.

@maurei
Copy link
Member Author

maurei commented Sep 12, 2019

Thanks for elaborating on this @roblankey. I would be interested in knowing more about common scenario in which Entity models are different from Resource models. Perhaps you could share your specific use-case of it?

@wisepotato
Copy link
Contributor

also @roblankey what kind of seperation of concerns are you talking about? If you could give a nice example this could give us a bit more idea if we are missing something we would like to introduce into our own code base.

The "many-to-many relationship conversation" is something im really interested in, what is meant by this?

@roblankey
Copy link
Contributor

Sure thing folks. All the use cases that really care about this separation are when you're talking about a difference between your data model and your resource model.

A lot of the newer development community however has one model tier and exposes those throughout using things like shadow properties and ORMs, which outside of small systems can perform more poorly than a properly designed data model. Either way, lets use as a quick example the Student/Course example in the project. A proper data model is going to look something like

Student

Id
First Name
Last Name
Email
Registration Date
Matriculation Date

Course

Course Number
Name
Department
Level
Professor

StudentCourse (M-to-M)

Student ID
Course Num
Quarter (YYYY-QQ)
Grade
Has Passed
Attempt Number

So a pretty simple E-E model with a many to many relationship between them. However, a JSON-API resource implementation has no such thing, as there is no concept of a many to many. A resource object either HasOne or HasMany, and to represent that model appropriately, you would combine information from the M-to-M StudentCourse entity into the resource models themselves.

Student

Id
First Name
Last Name
Email
Registration Date
Matriculation Date

@HasMany Registrations

Registration

Student First Name
Student Last Name
Email
Registration Date
Course Name
Course Quarter
Department
Professor
Grade
...

Course

Course Number
Name
Department
Level
Professor

@HasMany Registrations

Mostly so that you don't have to jump through multiple relationships to get to the information you're looking for. Storing a Registration for a Student goes through the Entity mapping relationship and AutoMapper profile to get the appropriate Course information, and save the simplistic many-to-many model.

Other use cases are quite a bit more simple where-in you may have a more complex, audited entity object, but a streamlined or transmuted representation of it for resource communication, e.g.

Entity

Id
Value A
Value B
Value C (JSON/XML)

Created Date
Created By
Updated Date
Updated By

Resource

Id
Value A
Value B
Value D (C.Property 1)
Value E (C.Property 2)

Created Date
Updated Date

Sorry for the simple examples! I hope these are at least halfway decent!

@maurei
Copy link
Member Author

maurei commented Sep 13, 2019

Hey @roblankey, I'm a little confused by your first examples (the latter for transforming data is clear). Hoping you could clarify a little.

I was wondering if at the time of implementing the [HasManyThrough] attribute was already available, and if at the time of writing these examples right now you are aware of this? Basically, what it means is that many-to-many relationships are supported.

In the simplest case, when the many-to-many join-entity is just the most minimal setup with two foreign keys, i.e.:

Student ID
Course Num

this attribute allows to completely abstract away the many-to-many join-entity, which allows to just query the many-to-many relationships out of the box, using: /students?include=courses and /courses?include=students.

In the more complex example, eg the first StudentCourse model you provided

Student ID
Course Num
Quarter (YYYY-QQ)
Grade
Has Passed
Attempt Number

it would still work out of the box but also abstract away all the "meta" information on the join entity (grade, etc). This means using the [HasManyThrough] attribute, it wouldn't be possible to filter on grade etc.

If I'm understanding correctly, the point you're making is the following. To get all information, you would have to expose all three as actual resources. Then;

  • /student?include=student-courses.course would be inconvenient to use, eg when wanting to construct registrations in a webpage or when filtering on grades
  • on it's own the the /student-courses resource would in practise never be very meaningful, you'd always want the student and/or course information (i.e. /student-courses?include=student,course) with it

As such, to overcome these inconveniences, smashing all three resources together into /registrations would result in a more intuitive API. And the Resource/Entity separation here would be Registration versus Student, StudentCourse and Course. Is this more or less the point you're making?

Thanks!

@roblankey
Copy link
Contributor

That's a good point @maurei. That portion of the E-R split may have been totally superceded by HasManyThrough.

@maurei
Copy link
Member Author

maurei commented Sep 27, 2019

As it turns out that a (significant) part of the usecases for ER separation are now covered by other parts of the framework (ResourceHooks, HasManyThrough), I think we will remove it for now. Still, having better separation of concerns by allowing for such split would be a really good feature to re-add in the future, but for now the development capacity is too limited to support it.

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

No branches or pull requests

3 participants