I have recently looked at an application, which uses the Model View Presenter pattern in the User Interface layer. There are Model classes like this:
Public Class OrderModel
Public Property OrderId() As Integer
Public Property OrderDate() As Date
Public Property RequiredDate() As Date
Public Property Freight() As Single
Public Property OrderDetails() As IList(Of OrderDetailModel)
Public Property Member() As MemberModel
End Class
In the Domain layer, there are domain classes like this:
Public Class Order
Inherits BusinessObject
Public Property OrderId() As Integer
Public Property OrderDate() As Date
Public Property RequiredDate() As Date
Public Property Freight() As Double
Public Property Member() As Member
Public Property OrderDetails() As List(Of OrderDetail)
End Class
Notice that Order and OrderModel are identical. There is a class called Model.vb in the UI layer, which has lots of code like this:
Return Mapper.Map(Of List(Of Member), List(Of MemberModel))(members)
Is it good practice to have two different Data Transfer Objects for each entity in the database? i.e. one DTO in the User Interface (OrderModel) and one in the model (Order) or is it better to have one DTO per entity for both layers eliminating the need to have the Mapper code?
In order to make right decision you should compare responsibilities of models in the User Interface layer and in the Domain layer.
Is it good practice to have two different Data Transfer Objects for each entity in the database? i.e. one DTO in the User Interface (OrderModel) and one in the model (Order) ...
It is quite common approach when people practice Domain-Driven Design. They have Domain Model that knows nothing about presentation (e.g. Order) and View Models (e.g. OrderModel) that are placed in presentation layer.
... or is it better to have one DTO per entity for both layers eliminating the need to have the Mapper code?
If your application is simple enough and your Order is simply DTO that is data container only and has no behaviour, you may have only one layer with DTOs.
Edit:
There is a quote from 12 ASP.NET MVC Best Practices article about working with DomainModel and ViewModels.
Model’s Best Practices
7 – DomainModel != ViewModel
The DomainModel represents the domain, while the ViewModel is designed around the needs of the View, and these two worlds might be (and usually are) different. Furthermore the DomainModel is data plus behaviours, is hierarchical and is made of complex types, while the ViewModel is just a DTO, flat, and made of strings. To remove the tedious and error-prone object-mapping code, you can use AutoMapper. For a nice overview of the various options I recommend you read: ASP.NET MVC View Model Patterns.
Related
What is the right way to create DTOs from business objects?
Who should be responsible for creating them? BO/DTO itself from BO/some static factory?
Where should they reside in code if I have, f.e. some core library and a specific service API library that I need DTO for? In core library next to BO(which seems incorrect)/in specific library?
If I have encapsulated fields in my BO how do DTO grab them? (obviously in case when BO is not responsible for creating DTOs)
As an example assume that I have some Person BO like this:
class Person
{
private int age;
public bool isBigEnough => age > 10;
}
I want age to be an internal state of Person but still I need to communicate my BO to some api. Or having private field in my class that I want to send somewhere already means that it should be public?
Are there any general considerations of how to use DTOs alongside business classes with encapsulated data?
___ Update:
In addition to approaches that #Alexey Groshev mentioned I came accross another one: we separate data of our BO class into some Data class with public accessors. BO wraps this data with its api(probably using composition) and when needed it can return its state as Data class as clone. So dto converter will be able to access Domain object's state but won't be able to modify it(since it will be just a copy).
There're multiple options available, but it would be difficult to recommend anything, because I don't know the details about your project/product. Anyway I'll name a few.
You can use AutoMapper to map BOs to DTOs and vise versa. I personally dislike this approach, because it's quite difficult (but possible) to keep it under control in medium/large sized projects. People don't usually bother to configure mappings properly and just expose internal state of their objects. For example, your isBigEnough would disappear and age would become public. Another potential risk is that people can map DTOs to/from EF/Hibernate objects. You can find some articles which explain why it's considered to be a bad practice.
As you suggested, a BO can create DTO by itself, but how would you implement this approach? You can add methods or factory methods to your entities, e.g. public PersonDto ToDto(). Or you can add an interface, e.g. public interface IDtoConvertable<T> { T ToDto(); }, and choose which entity or aggregate root will implement it. Your Person class would look like this class Person : IDtoConvertable<PersonDto> {... public PersonDto ToDto() {...} }. In both cases DTO namespace/assembly must to accessible by entities which sometimes can be a problem, but usually it's not a biggie. (Make sure that DTOs cannot access entities which is much worse.)
(C#) Another option is to return a delegate which creates DTO. I decided to separate it from (2), because entity doesn't really create DTO by itself, but rather exposes a functionality which creates DTO. So, you could have something like this public Func<PersonDto> ToDto() {...}. You might want to have an interface as in (2), but you get the idea, don't you? Do I like this approach? No, because it makes code unreadable.
As you see, there are more questions than answers. I'd recommend you to make a few experiments and check what works for you (your project) and what doesn't.
I think the answer to question 5 will address the other questions too.
Are there any general considerations of how to use DTOs alongside business classes with encapsulated data?
Remember, a DTO is solely to transfer data. Do not concern yourself with implementing any kind of rules in the DTO. All it is used for is to move data from one subsystem to another (NOT between classes of the same subsystem). How that data is used in the destination system is out of your control -- although as the God programmer you inherently know how it is going to be used, DO NOT let that knowledge influence your design -- and therefore there should be no assumptions expressed as behaviour or knowledge accessors -- so, no isBigEnough.
Quite a mouth-full of a question but its a OO principle I've struggling with. Lets say i have an e-commerce app and there is the concept of payment method, examples could be CreditCard, Paypal, Apple pay etc. The user has a choice of which payment method to select so i need to present them all in a list on the screen and depending on the selection this will be used to drive a UI, presenting different text/images/interactions as well as will be serialised slightly differently into a Payment request over the wire.
Here is some code:
public class PaypalPayment : PaymentMethod {
public string Token;
public string String;
}
public class CreditCardPayment : PaymentMethod {
public Address Address;
public CreditCard CreditCard;
}
interface PaymentMethod {
}
public class Booking {
public PaymentMethod PaymentMethod; //generic object
//or
public PaypalPayment PaypalPayment;
public CreditCardPayment CreditCardPayment;
}
So in my booking class i can either have a generic payment object referred to by the interface but i cant get to the underlying type without casting which sucks, as in reality them don't share any common properties doman-wise. Alternatively i have multiple properties which feels bad in a different way. The user can only select one payment method so the others will have to null or some kind of null object, i would have to either query an enum or ask each payment method if it is null. Also my payment method select screen is a bit more cumbersome as i cant just iterate on a generic type i have to explicitly build up the list.
In theory i could add some methods to the PaymentMethod interface, such as Serialise() or some UI presentation methods which all the payment methods have in common but then i would have to implement them in my model object which i don't want to do in my model layer.
Overall i dont have a clean solution for this in your typical object orientated language. I wrote this in c# but this could apply to any OO language.
Data seems to have been segregated away from logic in your design. As a consequence, Booking probably has to indulge in Inappropriate Intimacy with its Payment in order for the behavior to take place, hence the casting problem.
An idiomatic OO implementation would 1/ define a clear responsibility and 2/ encapsulate operations and data for it in the same class. Then you can have an abstraction on top of a family of these classes so that their behavior can be called uniformly by consumer code.
The Strategy aka Policy pattern might be a good choice for payment.
UI wise, it may be better to avoid using abstractions and have different UIs altogether for different payment methods. Or, you could have an abstract UI payment model whose concrete implementations know how to render themselves.
To have an interface and can't get to the underlying type is exactly what abstraction and loose coppling is striving for. This should not suck but should be desirable.
To get all possible instances to choose from, you could use a repository that returns a collection of all your payment methods.
To implement this repository you could use your favored ORM and load them from the database, use your favored IoC/DI Container and let it create all implementors of your interface, or hard code the creation. Whatever suits you needs and the needs of the project. If you use an interface for the repository as well, you can later swap the implementation.
In the Model View Controller pattern where should data transformation occur?
I have a Model that stores very specific mathematical data. I need to convert that data for a physics simulator(that only accepts data in a certain format) and I'm wondering where the code for that should sit? In general where do you place code that transforms one Model into another type of Model?
Personally, I like to put this code in the constructor of the derived type of model. In this way, the code that does the conversion is in the class that needs to use it. I find this way of organizing the code makes it easier to understand, test and maintain.
Using your example, say you have a class as follows (you did not mention what language you were using, so I'll give the code below in C#, but it is very similar in java):
public class MathematicalData
{
//members of class
}
Let's say you need to take the members of an instance of MathematicalData and transform them into another class named PhysicsSimulator. I would require the constructor to PhysicsSimulator to take an instance of MathematicalData as an input parameter, and then populate the members of PhysicsSimulator in this contructor:
public class PhysicsSimulator
{
//constructor
public PhysicsSimulator(MathematicalData input)
{
//put code here to use the members of input to populate members of this instance of PhysicsSimulator
}
}
If the only way you want to create an instace of PhysicsSimulator is by using an instance of MathematicalData, then I would not create a default constructor for PhysicsSimulator. In this way, the only way to create a PhysicsSimulator would be to pass in a MathematicalData instance.
It looks to me that you need to design an Adapter interface to achieve this. Making the constructor of the target(PhysicsSimulator) accept the source(MathData) object would tie them both such that when the source changes for whatever reason the target has to change.
An adapter will limit the changes to the adapter and will not force the target to change for every change in the source.
Hope this helps.
Here is a typical pattern I follow for an MVC web app. Input from the web lands in the Model, and then the Controller takes responsibility for transforming the web Model to the Business Tier model before calling the Business Tier action.
To keep the Controller from being bloated with transformation code, I'll offload transformations to AutoMapper whenever it's a fit.
DTO (Data Transfer Objects) are objects used to transfer information between multiple subsystems of an application, often separated by either a network or a process boundary. This is my understanding.
However, from Java perspective, do the subsystems/modules have to be on different JVM instances for the objects they use between them to qualify as DTOs? (I believe that a significant demarcation in architecture in terms of modularity and functionality between the subsystems would be sufficient.) What say?
Also, considering the objects exchanged by multiple modules in the SAME layer/tier of an architecture, don't these objects qualify as DTOs? Is a tier separation mandatory?
Thanks in advance.
Regards,
Nagendra U M
Because transferring objects between tiers requires some kind of serialization it is considered a DTO. Transferring objects between layers is generally done through the use of domain entities thus not requiring serialization.
So your DTOs generally do not have behavior only properties to hold data.
A little note: DTOs are often mistaken for anemic objects when you have entities with no behavior, only data. Or poltergeist objects when objects are only used to transport data in and out of methods or classes and then disappear.
As an example sometimes your data persistence mechanism requires you to implement or inherit interfaces or classes that you do not want to couple into your domain layer, so you create objects that inherit or implement the interface/class and transfer data to those classes for persistence.
class Person{
public string Name {get;set;}
public int Age {get;set;}
public void Validate(){}
public void DoSomething(){}
}
public class PersonDTO : TableServiceContext
{
public const string ContactTableName = "PersonTable"
public string Name {get;set;}
public int Age {get;set;}
}
And you would generaly have a class to assemble and disassemble these objects.
i'm investigating Nhibernate, jquery and WCF at the same time for a in-house project, and i was wondering why i couldn't have "clean" data classes.
From what i've read, a very good point in the nhibernate world is that my business class won't be linked to the framework.
I won't have
<SaveInTable("Thingie")> _
Public Class Thingie
<ColumnName("ThingieId")> _
Public Property Id as Integer
' accessors
End Class
but rather something like
Public Class Thingie
Public Property Id as Integer
' etc
And then
Public Class ThingieMapping
Inherits ClassMap(Of Thingie)
' etc, omitted for brevity's sake
What i don't understand is that if i want to list Thingies in a web page with jQuery, and if i want to use WCF webservices with jquery (it looks like the current trend from what i've seen on various tutorials), i find myself having to add DataContract and DataMember attributes to my Thingie class.
On the other hand, the classic ASMX webservices won't bother me and let me retrieve the Thingie class without worrying about adding attributes.
I have the feeling that i'm missing part of the picture here; it seems logical to try keeping the Thingie class mostly independent, but i haven't found examples so far.
So, do i have to abandon all hopes and stick to the classic webservices, or is there a way to have my WCF cake and eat it too?
I suggest you use DTOs to send over the wire - then you can decorate the DTOs with the necessary attributes.
This means, of course, that you must somehow map your domain classes to the DTOs and vice versa. If the mapping is trivial (+some other cases that satisfies some conventions), you can use AutoMapper for that.
Using DTOs has several benefits, the best being that you have a clear seperation of concerns - your NHibernate-mapped domain model is about modeling stuff in your domain, and your DTOs are for sending data over the wire. Then, if one changes, the other doesn't necessarily need to change as well.