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

How to share common schemas/resources/etc between yin and yang #19

Open
Doqnach opened this issue Aug 21, 2019 · 2 comments
Open

How to share common schemas/resources/etc between yin and yang #19

Doqnach opened this issue Aug 21, 2019 · 2 comments

Comments

@Doqnach
Copy link

Doqnach commented Aug 21, 2019

I am currently writing a JSON:API server implementation which will also have clients that will consume the API. The server is Symfony 4 using woohoolabs/yin. It contains a bunch of schemas, documents, resources, hydrators, etc.

I was looking in how to include these in a client-library, but everything extends stuff from the Woohoolabs\Yin namespace, whereas on the client side you are working from the Woohoolabs\Yang namespace.

Yang doesn't seem to share a base with Yin that would enable me to reuse code. What is the preferred way here? Write a totally separate client library, resulting in a high amount of duplicate code?

@kocsismate
Copy link
Member

kocsismate commented Aug 26, 2019

Hi @Doqnach ,

Yes, Yin & Yang are completely separated from each other.

The first reason I didn't want to share schema between the two libraries is that coupling the server and client implementation goes against the purpose of having an API - where the aim would be that the server and client could evolve independently. I think it's very difficult to achieve if you have a single underlying schema for both the server and client. Maybe you could separate the schema to an individual package and use semantic versioning when using it on the server and client, but I am not sure it works well on the long run. If you have any experience with sharing code between server and client, I am happy to hear it!

Furthermore, my aim with Yang was to:

  • make it possible to query every detail of the response by using the JsonApiResponse class
  • but in the same time, make it very easy to retrieve all attributes and relationships of the response by using the ClassDocumentHydrator

And I think it's enough to provide by a client library. In my opinion, if you need a somewhat useful schema on the client-side, you should map the response manually to domain object(s) of yours. But Yang can't do this automatically (and I am not into magical things - like the things Doctrine does for example).

I am on this viewpoint even more, because normally, the client-side doesn't (and shouldn't) contain much logic (except for some presentational one), and that's why usually the API response is only consumed in template code (e.g. Twig in PHP) where type safety - that a schema could offer - can't be made use of.

At least these are my experiences. I know that there are way different use-cases than mine, but my requirements against Yang were based on these assumptions when I started to build it.

I am curious about your thoughts!

@Doqnach
Copy link
Author

Doqnach commented Aug 27, 2019

the aim would be that the server and client could evolve independently

But... if the server changes the 'interface' (e.g. adds a field to a response), the client needs to follow? Now that means maintaining two separate but almost identical pieces of code.

I would then provide the hydrator in a (composer) client library that converts the JsonApiResponse body to a domain object at the "client" side on a 'GET' request to the server, which is the same process as converting the JsonApiRequest body to the exact same domain object on a 'POST' request on the "server" side coming from that "client".
In both cases the body is a string (stream) and the domain objects are the same, so conversion would be done in an identical way.

In this case this is backend-to-backend communication, where one backend is a "client" (generating a new resource) and requesting the other backend ("server") to persist it (save it in a datastore).

So right now I would have to make both backend services implement yin.

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

No branches or pull requests

2 participants