3

I'm creating a web application which on the client side consists of a Single Page Application (with Durandal) and on the server side an ASP.NET MVC site with a Domain Driven Design. The two are connected with a REST Api (Web API).

I have a relation between two entities, which on the database level is many-to-many. (Hotels <=> RoomTypes). Since in DDD a best practice is not to have many-to-many relationships I built it so that it can only be navigated from the roomtype to the hotel (since a hotel can exist without roomtypes, but a roomtype should always be associated with a hotel). The relation itself also has attributes (availability for example).

My current issue is how to associate a hotel with a roomtype however. Following DDD practices I would add a method AddHotel to the RoomType-class. The problem is that in the SPA, you can edit all the attributes of a roomtype (pictures, description, ...) and associated hotels in a single view. After editing these attributes, an update is submitted via the rest api. This means that everything gets submitted in one call to the server.

How would you structure the server and the rest based API so that:

  • the domain stays in place and there's correct validation inside the RoomType-class
  • you can post atomic updates from the single page application through the rest
  • there's no code duplication on the server and the single page application

1 Answer 1

4

You seem to hint at your own answer: don't submit everything in one go. If you think about it, what kind of actions would you like to be able to do in your view? One of them is apparently assigning hotels to room types. So for every action you want to perform in your view you either have a method you call on a endpoint controller, or if you want to work with commands, you'd form a AssignHotelToRoomTypeCommand with all the necessary data for executing that procedure, and send that command to an endpoint.
The more I think about it though, assigning a hotel to a room type seems a bit weird/backwards to me... Is there a reason you are modelling a room type as an entity and not a value object?

4
  • The problem is that everything is in one view. So it's possible that the user is creating a new hotel at the same time. So in order to do what you suggest, upon clicking save, I'd have to first create the hotel, then create the roomtype and then call AssignHotelToRoom. This looks very chatty, when you could do all of that in one call. Another thing is that AssignHotelToRoom seems a bit RPC-style and not very restful, but that's a complete other discussion. The reason I'm modelling roomtypes as entities is that a user can create roomtypes that can be reused.
    – Kenneth
    Commented Jul 16, 2013 at 10:21
  • At the moment what I'm doing is only exposing a ViewModel which holds the Hotels as a simple list on a RoomType. That way, a user can just post a complete RoomType. On the server-side this is then converted into a Domain Object. I'm not sure whether this is the right way to go though, since it adds another layer of complexity. I think this is more or less what CQRS is about
    – Kenneth
    Commented Jul 16, 2013 at 10:23
  • An SPA is usually one view, based on a task oriented interface. If you want one big viewmodel to go accross the wire, that's more of a CRUD app. I would advise you to use REST for querying, but use commands for writing. As for DDD: it is probably first and foremost about language, business language. PUT-ing a roomtype with an added hotel reference is obscure to anyone, even developers. Sending a command to assign a hotel to a roomtype is an attempt to model a business workflow. Nothing stops you from sending multiple commands in one go mind you. Commented Jul 16, 2013 at 10:50
  • Well, I think I'm going to stick with the ViewModel-approach for now. It provides a nice separation between the REST-API and the Domain Layer. It also allows the API (and subsequently the SPA) to evolve separately from the Domain. Thanks for the help!
    – Kenneth
    Commented Jul 16, 2013 at 20:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.