In a blog application developed using domain driven design a 'Post' entity has a related collection of tag entities.
On creating the post (e.g populating the object from the UI) i would like to call a third party API via REST which takes the content of the post and extracts semantic tags (link text) for association.
Main Question : What is the best way to design this...
Is it best designed so that the Post entity would call a domain service such as PostServices.GetTags(Postcontent) passing its content and retrieving back a list of tags.?
** PostServices.GetTags would then inteface with the REST API via a further wrapper class.
Or should the third party API be wrapped as a repository?
Should the function Post.GenerateTags(), should not exist within the domain entity at all?
Further questions :
1 : I have also read that it is not good practice to have a domain entity converse with a domain service. Is this true?
2 : Is it ok to get a reference to the PostServices domain service via a factory creation method. e.g...
IPostService PostService = ServiceUtil.GetPostService();
return PostService.GetTags(Post.content);
3 : Is it acceptable to have the domain service coupled to a third party api?
4 : Should the domain entity simply just know how to deal with the tags received via the application layer which has called the REST API.
Slowly trying to get my head around DDD, however I can't seem to find any examples of how to implement this sort of thing.
In a Blog application, a Post is an Entity and a Tag is a value object. A Tag hasn't got identity. You should have:
PostsRepository
Post (Entity)
Tag (value object)
A Post has got a list of tags.
Questions:
1 : I have also read that it is not good practice to have a domain entity converse with a domain service. Is this true?
Yes, itsn't a good practice. You entity hasn't want to be coupled with a domain service. If you do that, then you couldn't reuse them later. Did you have consider to fire a domain event. You can tell your service domain do something fire domain events.
2. : Is it ok to get a reference to the PostServices domain service via a factory creation method. e.g..IPostService PostService = ServiceUtil.GetPostService(); return PostService.GetTags(Post.content);
Yes, it's possible. A factory method could return an abstract class or an interface. This is a good Software Design Principle "code to an interface not to an implementation". If you do this, you'll be able to change your implementation later and you won't have to change yout client code.
3 : Is it acceptable to have the domain service coupled to a third party api?
I don't recommend you this, but it is acceptable.
Sorry, I don't understand question 4.
Look this link. I hope it help you.
https://stackoverflow.com/questions/901462/ddd-where-is-it-most-appropriate-to-get-a-list-of-value-objects/901562#901562
Related
I have read through the documentation many times over and search all over for the answer to this question but have come up short. Specifically I've looked at Defining the service and the Cornice API for a service and at Defining resource for resource.
I'm currently building a REST API that will have a similar structure to this:
GET /clients # Gets a list of clients
GET /clients/{id} # Gets a specific client
GET /clients/{id}/users # Gets a specific clients users
What would be the best way to go about this? Should I use a service or a resource or both? And, if both, how?
Resources are high-level convenience, services offer lower level control.
I am just learning cornice myself. Looking at the source code, a Resource creates Services internally, one for the item and one for the collection (if a collection path is specified). The resource also adds views to the services for each method defined with an http verb as the name or in the form collection_[verb].
So there is little difference except that resources are a neat, structured way to define services.
The resource decorator uses a url for the collection, as well as a url pattern for an object.
collection_path=/rest/users
path=/rest/users/{id}
The resource decorator is best used in view classes where you can use get/put/post/delete methods on the objects, as well as collection_get, collection_put, etc. on the collection. I have some examples here:
https://github.com/umeboshi2/trumpet/blob/master/trumpet/views/rest/users.py
Since I make heavy use of the resource decorator and view classes, I haven't found a need for the service function, but it allows you to create get,put,post decorators that wrap view callable functions.
If you are using backbone.js on the client side, the resource decorator and url examples work well with the Backbone collections and models.
I am writing an application that is consuming an in-house WCF-based REST service and I'll admit to being a REST newbie. Since I can't use the "Add Service Reference", I don't have ready-made proxy objects representing the return types from the service methods. So far the only way I've been able to work with the service is by sharing the assembly containing the data types exposed by the service.
My problem with this arrangment is that I see only two possibilities:
Implement DTOs (DataContracts) and expose those types from my service. I would still have to share an assembly but this approach would limit the types contained in the assembly to the service contract and DTOs. I don't like to use DTOs just for the sake of using them, though as they add another layer of abstraction and processing time to convert from domain object to DTO and vice versa. Plus, if I want to have business rules, validation, etc. on the client, I'd have to share the domain objects anyways, so is the added complexity necessary.
Support serialization of my domain objects, expose those types and share that assembly. This would allow me to share business and validation logic with the client but it also exposes parts of my domain objects to the client that are meant only for the service app.
Perhaps an example would help the discussion...
My client application will display a list of documents that is obtained from the REST service (a GET operation). The service returns an array of DocumentInfo objects (lightweight, read-only representation of a Document).
When the user selects one of the items, the client retrieves the full Document object from the REST service (GET by id) and displays a data entry form so the user can modify the object. We would want validation rules for a rich user experience.
When the user commits the changes, the Document object is submitted to the REST service (a PUT operation) where it is persisted to the back-end data store.
If the state of the Document allows, the user may "Publish" the Document. In this case, the client POSTs a request to the REST service with the Document.ID value and the service performs the operation by retrieving the server-side Document domain object and calling the Publish method. The Publish method should not be available to the client application.
As I see it, my Document and DocumentInfo objects would have to be in a shared assembly. Doing this makes Document.Publish available to the client. One idea to hide it would be to make the method internal and add an InternalsVisibleTo attribute that allows my service app to call the method and not the client but this seems "smelly."
Am I on the right track or completely missing something?
The classes you use on the server should not be the same classes you use on the client (apart from during the data transfer itself). The best approach is to create a package (assembly/project) containing DTOs, and share these between the server and the client. You did mention that you don't want to create DTO's for the sake of it, but it is best practice. The performance impact of adding extra layers is negligible, and layering actually helps make your application easier to develop and maintain (avoiding situations like yours where the client has access to server code).
I suggest starting with the following packages:
Service: Resides on server only, exposes the service and contains server application logic.
DTO: Resides on both server and client. Contains simple classes which contain data which need to be passed between server and client. Classes have no code apart from properties. These are short lived objects which survive long enough only to transfer data.
Repository: Resides on client only. Calls the server, and turns Model objects into DTO's (and vice versa).
Model: Resides on client only. Contains classes which represent business objects and relationships. Model objects stay in memory throughout the life of the application.
Your client application code should call into Repository to get Model objects (you might also consider looking into MVVM if your not sure how to go about this).
If your service code is sufficiently complex that it needs access to Model classes, you should create a separate Model package (obviously give it a different name) - the only classes which should exist both on server and client are DTO classes.
I thought that I'd post the approach I took while giving credit to both Greg and Jake for helping guide me down the path.
While Jake is correct that deserializing the data on the client can be done with any type as long as it implements the same data contract, enforcing this without WSDL can be a bit tricky. I'm in an environment where other developers will be working with my solution both to support and maintain the existing as well as creating new clients that consume my service. They are used to "Add Service Reference" and going.
Greg's points about using different objects on the client and the server were the most helpful. I was trying to minimize duplicate by sharing my domain layer between the client and the server and that was the root of my confusion. As soon as I separated these into two distinct applications and looked at them in isolation, each with their own use cases, the picture became clearer.
As a result, I am now sharing a Contracts assembly which contains my service contracts so that a client can easily create a channel to the server (using WCF on the client-side) and data contracts representing the DTOs passed between client and service.
On the client, I have ViewModel objects which wrap the Model objects (data contracts) for the UI and use a service agent class to communicate with the service using the service contracts from the shared assembly. So when the user clicks the "Publish" button in the UI, the controller (or command in WPF/SL) calls the Publish method on the service agent passing in the ID of the document to publish. The service agent relays the request to the REST API (Publish operation).
On the server, the REST API is implemented using the same service contracts. In this case, the service works with my domain services, repositories and domain objects to carry out the tasks. So when the Publish service operation is invoked, the service retrieves the Document domain object from the DocumentRepository, calls the Publish method on the object which updates the internal state of the object and then the service passes the updated object to the Update method of the repository to persist the changes.
I am pleased with the outcome as I believe this gives me a more robust and extensible architecture to work with. I can change the ViewModels as needed to support the UI with no concern over poluting the service(s) and, likewise, change the internal implementation of the service operations (domain layer) without affecting the client application(s). All that binds the two are the contracts they share. Pretty clean.
You can serialize your domain objects and then de-serialize them into different types on the client. Both types need to implement the same data contract. All serializable types have at least a default data contract that includes all public read/write properties and fields.
Our third party API provides two different web services but have identical methods, models. Nevertheless they only differ on URIs (Web Service Path, Action Path [Operation Contract].
So I have decided to:
Generate the code from their wsdl using VS.
Edit the namespacing to use the same and to be "Common" and not use the service reference instead i use the Reference.cs edited code.
Create a new proxy that will handle the correct URI of the service to use (wrapped the Reference.cs inside of it).
Now, I having an issue with the "Method1", because they have different Action Name. Having an exception of:
"Server did not recognize the value of
HTTP Header SOAPAction:
http://www.api.com/service/Method1"
I just notice that it the correct action name is: http://www.api.com/service1/Method1
The question now is, is there any configuration or behavior that i can use to correct the action name for each method for each service?
Or as long as they keep on adding contracts for each implementation of the API, i should also keep on adding the contracts for each, and just use the ChannelFactory for this?
Please help, thanks.
I ended up directly using the ChannelFactory when faced with the same problem
In my implementation, I had a base interface that had all the common methods to the 2 APIs. Then I had 2 seperate intefaces - one for each 3-rd party API version - that inherits from the base interface and adds methods and [OperationContract] attributes that varied between the two implementations.
When instantianting ChannelFactory<> I used one of the child interfaces. Helped to keep the consumer code clean and maintainable
I have a RESTful server and need to create the client in a Cocoa app.
I have a model called Resource. When I GET /resources, my server returns all resources in JSON.
I have a model called Client that owns many resources.
The Client has an instance method -(NSMutableArray*)resources
An NSArrayController manages the resources. The first time the above method is called, it asks the REST server for the client's resources.
My question is this: who should create the request, dispatch the request, and populate the array: the Client class or the Resource class (with something like -(NSMutableArray*)resourcesForClient:(Client*)client )? Or maybe neither, instead there being an API class that receives the model name and some filters and returns the array?
Unless there is a good reason a resource should know about clients, or speak with servers, it is probably a good idea to keep its responsibility minimized. The client has a collection of resources, so it is ok for it to know what a resource is, and manage the requests and management of resources.
I would go with neither if both Client and Resource are part of the business model. Presumably a "Client" in this instance is a customer not a client in technical client-server speak.
Edit:
Your business model should be all about the rules and objects associated with the business. I would class the problem of getting the objects from a particular backing store as not part of the business model in much the same way as I would class getting the objects from a user as not part of the business model.
Therefore your "get from the server" API should be separate.
Try to understand what the options might be with use of WCF Data Services, Basicly i'm trying to abstract a 3rd party http API by making a RestFull services from the 3rd Party set of api calls. On top of this im intrested in the Odata representation and Api support that Data Services.
Example 3rd Party Call,
1)GetAll Vehicles
I want to represent it in a restfull call http://localhost/Vehicles
2)GetVehicleLocation(vehicles)
I want to represent it in a restfull call http://localhost/Vehicles(1)/Location
The challenge im looking at how can i invoke the List {to make it simple} from the web service call. This part is striaght forward where i need some guidance is when were doing the Call 2), since the Location infomation is based off a webservice call passing the Vehcle, Linq to Object is assuming the POCO are filled if im understanding correctly..
This article
Data Services Streaming seems to be on the path...
I'm presently investigating a similar scenario. Since the primary use case for WCF Data Services is exposing your database tables through Entity framework, finding good information on doing anything else is a bit thin on the ground.
What you are trying to do is fairly straightforward in fact, and can be simplified by using the WCF Data Services Toolkit; you want to wrap odata around what
You will need to expose two entity types at the root level, Vehicle and Location
You need a DataService<MyDataContext> as the entry point of the service, this will need to define two IQueryable properties for Vehicles and Locations. You may not really need to access Locations at the root level, but its the only way to make this work with the underlying reflection provider. Without having Location at the root level the service will not expose the metadata for the Location entity.
Your Vehicle entity will need a Location property with a [ForeignProperty] attribute
You must implement a repository for Vehicles having methods named; GetOne(string id), GetAll() and GetLocationByVehicle(string id) method, the id will be the VehicleId that you need to make your api call.
making a Get request on /Vehicles will invoke the GetAll() method on the repository, /Vehicles(1) will invoke the GetOne() method and /Vehicles(1)/Location will invoke the GetLocationByVehicle() method passing in the Id '1'.