I'm refactoring a application to DDD, and so far so good but i got a doubt about some responsibility and what are the best approaches to solve it.
The application is a web app that call center agents use, with CRM features, the backend is a REST API.
The use case is as follows: The agent calls to a customer and need to collect some information / offer promotions etc.
After calling the customer and talked to him, he needs to fill some information for this contact attempt, some of that information is combo box with data filled from the database, and it sends a POST with the IDs of the entities to a endpoint to register it.
So we have a endpoint contactAttempt that receive the data, customerId, agentId, some combo box info (subjectId, reasonId, extraInfo1, extraInfo2), the extra info doesn't call that, but just to simplify.
That information is deserialized to a DTO object that is passed to a application service, which consult the respective repository to check if the ids are valid and return the Entities, if the entities are not found, it throws a exception that the controller catches and answer the client with a message.
If all the entities are valid, there are some domain rules, like if is the first contact with the customer, sends a welcome e-mail, and other stuff.
My doubt is with this steps of fetching entities from the Repository, it should be like that or should i fetch it in the controller, and if all that i need is present, then i pass to the domain service with just the logic needed to apply the business rules?
What are the pros and cons of the mentioned approaches?
Is there other approaches?
In the context of a MVC, what is the responsibility of the Controller?
The MVC is responsible to deserialize the HTTP request in a message for the "application layer".
So it should get from the querystring/body/headers all the values needed and pass to a service as immutable values (command). This because the application service (handler, whatever) should execute the command transactionally, and if the entities (so, the behavior) are accessed outside the application layer, you can't assure that no modification happens outside the application layer.
Related
I am trying to add user and friend services using lagom framework. I read lagom persistent doc but still not able to understand how should I decide on entity id? Since it should be unique to retrieve it back. The random uuid generated is one option but that would be unusable since while sending command those uuid will not be available to other user/services.
Here are two solutions I can think of:
1) use email as entity id.
2) push the uuid and user name/id in database so that service retrieve uuid and then send command.
As per my understanding Solution 2 is two step process and defeats the purpose.
Solution 1, for other services like friend service there might be cases which can be duplicated or needs to send more information to retrieve the entity id.
Also I couldn’t find a better way to implement dean on services in this framework. Is there a way to do that?
There are no simple answers to your question, because it all depends on how the interaction between the services will look. But you should think about Entity Id as a unique identifier which also doesn't change in time. Changing Entity Id means creating new entity. In my opinion, email is not a good candidate for an Entity Id, because user may change it and also use more than one. I would go for UUID and would keep track on emails, plus expose methods which can handle communication between the services using for example user email (one of his emails), phone number(s), 3rd party service Ids, etc.
Assuming a resource X(http://example.com/a/foo/7) from rest-service A needs to hold a reference to a second resource Y(http://example.com/b/bar/1) from rest-service B.
How would one persist the reference?
Currently I'm storing the whole URI (as a string) of Y in the persistence layer of service A. Is this a common/valid approach?
It seems wrong to me to extract the id(1) out of Y's URI as I would implement assumptions about the URI structure of service B in service A. Is this correct?
How do you solve this problem?
Thx!
Lets discuss it with some actual business domain , then the answers will make sense.
So first example:
X represents Order Entity in Amazon Order Service, Y represent Customer in Customer Service.
Now while fetching the order from Amazon from Order Service, you also want to show some basic customer detail and link to customer Object to go to Customer Detail Page.
In this case what I would do is while creating the order copy some basic attributes of the customer in Order Entity (customerName , customerArea).
Also store customerId, customerType. And as the API for fetching customer is Public and also exposed to various internal services, Order Service will do a Service discovery and create URL and call. In these cases generally customer service will not stop supporting the old way (even if they are building a new one).
So storing just the id is a solution.
CASE 2:
Amazon Order Entity wants to store delivery details and delivery partner is some third party entity like DHL , then if DHL provides a URL to fetch the delivery updates to the order, in those cases I will just store the URL.
Generally I will prefer to store id and service type and some basic details to create a good customer experience and also avoid hitting one extra service api for getting the basic detail like customer name.
Storing direct URL makes sense when its a third party URL.
Also if you can give certain example of your business case like this, we can discuss better
IMO references should be stored as is. How you get the actual data from reference should not be part of the data but the logic which may change from time to time.
I will store them as reference of external reference (just to paint the picture that reference is out side our service) and coupled it with a logic to query the data.
URL is very volatile and may change. As a rule of thumb you should never keep urls in you database and should rely on service discovery to identify where the service is even if its within you own infra.
Its not an assumption, its a contract, which may changes and if it does, your service will be dependent service and has to make due changes
Also by your logic, even if you keep url, response to it is still a contract that both of you adhere to.
I've come from a background of ASP.Net MVC where when the user wants to create a new entity the server returns values to populate drop down lists(for example).
Now I'm doing a UI that is invoking a REST Api. I have my urls for creating/retrieving etc but this is purely for actual resources. How would the REST be defined to get data to populate the create form.
For example:
a user wants to create a new order. They go to the 'create order' screen and need to select their payment method. They have 3 payment methods (card, paypal, amazon) but the logic on the server side knows that amazon cannot be accepted on this order. How would I go about letting the UI know what can be populated in the drop down list using REST?
I can't seem to get this to fit into REST principles but then I don't want the user to submit amazon and then the server return a Bad Request, just seems bad implementation.
Thanks
For a simple application, there are 2 restfull apis managing users' information.
For example, api A is defined as /users which return a list of users. api B is defined as /user/{id} which return a user identified by his id.
However, the front page using the api A is a summary page displaying a table of a users which only need a few properties of a user, like name, age, gender, etc.. When refer a details of a user's information, there are much more properties are needed, like social security number, bank accounts, and there properties are not stored in the database but in some other system.
So, should I using different apis for there these two scenario, like /userSummaries and /userDetailes/{id} and just using apis I mentioned above?
Any advice will be appreciated.
You should have an api for every bounded context.
That being said, you should somehow map the write and the read models to the api endpoints. Aggregates commands should be mapped to put/post/patch/delete endpoints. Read-models queries should match the get api endpoints.
UPDATE:
So, should I using different apis for there these two scenario, like
/userSummaries and /userDetailes/{id} and just using apis I mentioned
above?
Yes. You should have an API end point to each Read-model.
See https://vimeo.com/41763224 and https://yow.eventer.com/events/1004/talks/1047
Yes, I would separate the two APIs. In the API layer, you have different models for the response(eg. UserSummaryModel, UserProfileModel). These models will act as view models or DTOs(data transfer objects). They are anemic classes that contains only getters and setters. The rich domain which is in a separate project will contain the User(and other domain models) business logic, constraints, validations, etc.
So in the API layer, you have to map the view models to the domain model. You can manually do the mapping or use Automapper.
#Constantin GALBENU is right what you should have an API for each context but this also depends on your application because there could be cases where you need an API to fetch data from two contexts.
I just want to add that you should not confuse the Domain of your application with the Domain of your API(s). I.E. you can have a generic API that is able to standardly hook to any of your BoundedContexts and expose their functionality either via concrete configuration or some automatized method.
This not however mean that your API code is part of you App's Domain since the API is only concerned with answering requests/logging/etc. - all things specific to an API.
Without moving away from the RESTful paradigm, how could you model object validation in a RESTful way? Best to explain the theoretical use case I've come up with...
Imagine you have a system with a very thin web layer making calls to back-end RESTful services. Say a user visited a registration form and submitted it, the web layer would send the unvalidated data straight to a back-end service and, if the service responds with validation errors in JSON format, these can be sent back to the user as HTML.
However, imagine we want to have AJAX behaviour on the form. For example, the user enters their email address and we want to validate using AJAX, sending an error to the user if their email address is already registered.
Would it make sense to implement a single call to validate just the email address, or could the whole object be sent and validated in a back-end service? If the latter, what URL could you use to only validate an object, rather than actually create it?
In the past I have used the notion of a sandbox sub-resource to do what you are suggesting,
http://example.com/customer/23/sandbox
This allows me to POST deltas and have the changes applied and validated but not actually committed. This works quite well for the traditional "save/cancel" type dialogs.
However, I found dealing with those deltas to be a real pain, so I developed a different media type that recorded a sequence of events on the client and then posted that document to the sandbox resource. By replaying the sequence of events I could update and validate the server side resource in a simpler fashion.
Later on I realized that I really didn't need the distinct "sandbox" resource and now I just post the "sequence of events" document directly to the resource it is affecting. I have some data in the document itself that determines whether the changes are going to be permanent or just transient. It just depends if the user has pressed the save button yet or not.
Validating a single form field can improve user experience while the user is filling the form, but when the form is submitted, I would validate the whole object, because it's less error prone. The URL can be simply https://mysite.com/users/emailvalidator for validating the e-mail only (a single field), and the form could be POSTed to https://mysite.com/users (the whole object). In the former case, the URL tells clearly that the resource you want to use is an object which is able to validate an e-mail.