What are the Slack Archives?

It’s a history of our time together in the Slack Community! There’s a ton of knowledge in here, so feel free to search through the archives for a possible answer to your question.

Because this space is not active, you won’t be able to create a new post or comment here. If you have a question or want to start a discussion about something, head over to our categories and pick one to post in! You can always refer back to a post from Slack Archives if needed; just copy the link to use it as a reference..

Hello again πŸ™‚, and lets start this week with some extensive question … sorry i

UPWG9AYH2
UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

Hello again πŸ™‚,
and lets start this week with some extensive question … sorry in advance^^

the question rises very often, where (or in which layer) to implement specific stuff like connections to external system etc. I tried to find a β€œdefinite” answer in the docs but i think there is no.

To break question down: Implement a client on client layer or implement an API in Zed Layer?

For example connecting external user access management that can be called via an Rest-API. You could put it into a separate api module like β€œuser-access-api” like spryker does for many eco-modules like payment integrations …
Then you would have for a typical call from Yves the route

Yves->MyModuleClient->MyModuleGatewayController->MyModuleBusinesslogic->MyModuleApi->MyModuleApiClient->APICall

or you could put code just into the client layer which seems more obvious at the first view. At least if the functions are very simple and no complex business logic is needed in spryker. For example a isUserAllowed($userID) function which will just return if the user is allowed doing specific stuff or not. The chain would be
Yves->MyExternalServiceClient->isUserAllowed

My present opinion is, that whenever Zed has also to β€œknow” about whats going on there, implement an API and everything on top (separate Zed client for this module etc). Because you have to call Zed anyway and do everything that is needed also in Zed backend.

Whenever it should be β€œlightweight” and fast and Zed don’t need to know about -> implement a client on client layer.

But then someone could argue: β€œWhy not always implementing a client and use them in both, yves and zed?” This is a valid argument in my eyes since if you decide to implement a client on client layer first this would keep the door open for later changes. All other β€œconsumers” are added around.

Especially when the external service is providing a mix of β€œlightweight” functions like β€œisAllowed” and more heavy ones where something in Zed has to be updated like β€œfetchUserInfo”.

However, is there a thumb rule / general recommendation when to go for which approach? I know, it depends heavily on the use case, but maybe there might be facts/thoughts that definitely would break the one or the other way.

Best

Comments

  • U01LKKBK97T
    U01LKKBK97T Posts: 287 πŸ§‘πŸ»β€πŸš€ - Cadet

    https://documentation.spryker.com/docs/programming-concepts says: A Client is the place where the implementation of the communication between the front-end application and all the surrounding resources is built. [...] Sometimes, there are Clients that connect directly to an external resource. In this case, there is only a Client for this module, but no Commerce OS or front-end parts.

    That being said, the client layer would be the right thing to do.

    If I'm getting your question right, you're also wondering where to put the client logic. Imho, it depends on whether your client needs Zed (e. g. for querying data, accessing file system, ...) or not.

    If it is depending on Zed, you would probably want to have all the logic in your Zed module and make the client call it via stub > gateway controller > facade and so forth. Layers other than Zed can use the client then, Zed modules can use it by calling the module's facade right away.

    If it's about calling an external service, I would put all logic into the client and leave away the Zed call to save that additional http call.

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    Hi Kay, thanks for your response and feedback.
    We struggle very often where to put the logic especially from the yves view.

    Like i said, just fetching live if a user is allowed to do this or that, i think the overhead communcating with zed which will also just delegate the call via api-module to the external ressource is too much

    But if you look at some at the eco modules you will have the client actually in the Zed layer in the corresponding β€œapi” module … for example all the payment modules have api modules which are responsible for the direct communication between spryker and the external ressource. This is because just zed should communicate with the external ressource.

    While some modules like the fact-finder have a client in client layer …

    So why not using a client from the client layer every time? Or is using a client from zed layer something that should not be done in spryker? But redis is the counter example …

  • Sylvain Gaffie
    Sylvain Gaffie Sprykee Posts: 18 πŸ§‘πŸ»β€πŸš€ - Cadet
    edited July 2021

    if I understood your question right, you have an external API you want to use. But the final output will be in Yves.

    This is how you should do it:
    Yves>client>zed>client>external service

    Clients are not for yves to zed communication only. And in general, Yves should not do heavy logic. (calling external APIS)
    Now, it's your call if you want to save time and do straight from yves.
    There are also some cases (ie.getting reviews) where calling an external API from Zed make little (or no) sense.
    At the end of the day you need to decide if you think that data belongs to the backend or not.

  • U01LKKBK97T
    U01LKKBK97T Posts: 287 πŸ§‘πŸ»β€πŸš€ - Cadet

    Maybe this would be a good rule of thumb:

    a. If you need to call an external service, process the response and forget it, then you could opt for a client.
    In my latest project, we were using a remote service for validating a company's vat id during registration form submit. Hence, the yves form was just using the client's return value to fire a validation constraint, if needed.

    b. If you need to persist data, then Zed might be a better place.
    Payment is a good example, e. g. saving a payment transaction id along with the sales order.

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    @ULMK1EG9Z

    This is how you should do it:
    Yves>client>zed>client>external service
    Clients are not for yves to zed communication only.

    The second statement would argue against the first one or do i missunderstand it?πŸ€”

    The thing is, if you start implementing the stuff in a separate zed api module then you are forced to always go over the zed client with all its overhead, even its a β€œlightweight” call, like your example with reviews … on the other hand (my naive thought) if you always put it into a client, you are felxible in every direction … you can let yves use the client for β€œlightweight” calls, but also let zed use this client to get the raw infos from and process it in zed. But i wonder why the most spryker eco modules dont follow these approach since i see no disadvantage till now …
    The only two clients that get used from backend too is just the redis and elasticsearch client which getting used from zed and from yves side … but unfortunately they are core part of the spryker system and i dont know if this can or should be transferred to all other non-spryer parts of the application …

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    @U01LKKBK97T Yes, this is my opinion right now too, but here you could also argue … put the actual api call into client layer and let zed use the client and do further process in zed module … means flexibility in both directions

  • Sylvain Gaffie
    Sylvain Gaffie Sprykee Posts: 18 πŸ§‘πŸ»β€πŸš€ - Cadet

    Sorry, this might make it clearer.
    Yves>client1>zed>client2>external service

    So you do a regular call to zed via the client. Then, Zed makes the call to the external API VIA another client that you wrote specifically for that API.
    The point is, Clients are made for any communications from ANYWHERE to ANYWHERE. not just Yves>zed.

    And to decide, think about this: to prepare an api call, you might need to have some logic. (preparing transfer, dealing with permission, save requests in db) and you should not do that in Yves.
    When you get the reviews, you just straight display them, so it's fine, but if you needed to store them, that would make it a zed job.

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    Like for payments .. at first view you think its just backend related, so own module in zed is correct … but then you have some api call that isnt touching zed at all … if you have the api implementation, you are forced to do a zed call … or you have to implement a client now beside the zed implementation which is awkward in my eyes^^

  • U01LKKBK97T
    U01LKKBK97T Posts: 287 πŸ§‘πŸ»β€πŸš€ - Cadet

    I'm getting your point.
    Zed shouldn't do more than the persisting part then.

  • U01LKKBK97T
    U01LKKBK97T Posts: 287 πŸ§‘πŸ»β€πŸš€ - Cadet

    In case of payment it should also follow the approach that you just suggested:
    1. Call the external service from client layer and return the response e. g. as a transfer object.
    2. Pass the response transfer to Zed for persisting.

  • Sylvain Gaffie
    Sylvain Gaffie Sprykee Posts: 18 πŸ§‘πŸ»β€πŸš€ - Cadet

    I am not sure who is replying to whom haha. But that is not what I suggested. (in case you meant me)
    Reviews from say, Amazon> you can do the call yves>client>amazon
    Any heavy things (especially payments processing) should be done in zed. (like it's done now when you place order at checkout.

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    @ULMK1EG9Z you mean, whenever there is logic needed to prepare the call, its a zed job? I cant think of any call wheres no logic needed … also for reviews you need some kind of token/id or whatever to pass to the client so that you get the reviews for the right product

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    At the end i am a fan of having a central gateway to stream all requests …. this might be zed … but not at any price^^

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    In case of payment it should also follow the approach that you just suggested:

    Yeah thats my assumption too but than i found that the most eco modules dont follow that and i wondered that there might be a reason … maybe it could also be that this follows an old approach before clients layer where common in spryker … also possible, i dont now^^

  • U01LKKBK97T
    U01LKKBK97T Posts: 287 πŸ§‘πŸ»β€πŸš€ - Cadet

    Likely, yes.
    My assumption is that most of the "client code" is built into Zed because the demoshops just don't need it anywhere else.
    Let's not take everything for granted just because Spryker did it that way. Probably Spryker themselves would solve a few things different nowadays if they had the time to catch up.

  • Sylvain Gaffie
    Sylvain Gaffie Sprykee Posts: 18 πŸ§‘πŸ»β€πŸš€ - Cadet

    @UPWG9AYH2 can you send me a module (and file) that you think doesn't follow the right "standard"? just curious. Also I want to make sure we talk about the same thing.

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    @ULMK1EG9Z look at https://github.com/spryker-eco/computop-api/tree/master/src/SprykerEco/Zed/ComputopApi
    The client itself is implemented in the business logic of zed … no client layer at all … here i would expect at some point the client layer call

  • UPWG9AYH2
    UPWG9AYH2 Posts: 509 πŸ§‘πŸ»β€πŸš€ - Cadet

    @U01LKKBK97T yes i think so too … but the discussions that rises are very valuable in my opinion πŸ™‚ So thanks a lot for putting effort into this!

  • U01LKKBK97T
    U01LKKBK97T Posts: 287 πŸ§‘πŸ»β€πŸš€ - Cadet

    Cheers.
    I also think that it is a good basis for discussion. There's always room for improvements, sure.