Saturday, October 24, 2009

DTOs, Business Entities and Persistency

(Cross post from IRefactor)

When designing an application, one can easily confuse DTOs, Business Entities and Persistency.

Using the following simple examples I will demonstrate design considerations and thoughts that will dispel some mists.

Consider that you want to represent an audio or a movie located on a web page.
When you visualize such an object, the first thing you probably see is the data that characterizes it. No surprise here. You applied, without knowing it, an "Information Expert" pattern when you visualized the object's knowledge responsibilities.

So, what are they? Clearly such an object will have:
  • Uri - object's URL
  • Content - object's content
  • DateCreated - object's creation date
  • Etc...
I will name this object a "Resource", since it represents a resource being located on a web page (be it a movie or an audio).

But wait... here you go; Meet the DTO object. A DTO is a simple container for a set of aggregated data that needs to be transferred across a process or network boundary. It should contain no business logic and limit its behavior to activities such as internal consistency checking and basic validation.

The Resource object is rather simple, it's a mere placeholder for the object's attributes and as such represents a DTO.
Now, let's say that a Resource object should be persisted to some store.

Basically, we would like to introduce a "Save" functionality that will persist a Resource object. The question is: Who's responsibility should it be? Using the Information Expert pattern again will reveal that functional responsibility (as a "Save" operation) is a sole responsibility of a class with the most information required to fulfill it. Hmmm... Isn't it a Resource class? As a Resource class "knows" exactly the information it wants to persist, it implies that the Resource class should have the "Save" responsibility.

I know... I know... Didn't we say a minute ago that a DTO shouldn't contain any business logic? By adding a Save responsibility to the resource class we turned it into something else. We turned the Resource into Business Entity. A business entity is an object that is responsible to solve domain requirements by collaborating with additional business entities.

Let's see what are our design options for creating a Resource business entity.

Option I: A Resource business entity inherits a ResourceDTO.

Though it's tempting to select the above solution, you shouldn't take the path (unless the requirements are very very simple). Remember; One of the principles of object oriented design is to favor object composition over class inheritance. There are many reasons for which the principle holds, but I am not going to discuss all of them here.

It does not make sense that Resource "is-a" type of ResourceDTO; You are not going to transfer the Resource object across boundaries. Moreover, such a design may violate the Single Responsibility and Open Closed Principles. The "Save" method is going to be bloated with a specific logic of how to connect to a certain store - which is clearly not Resource's responsibility. Changing a store, having more than one store or changing what to store will require Resource modifications - which violates the OC principle.

Option II: A Resource business entity passes a Resource DTO to a specialized Resource data access entity.
All the specific logic of data access is captured in a specialized ResourceDal object. Any change in store, will change only the specialized object. The ResourceDal object will receive a Persistent Resource DTO object, thus decoupling the Resource entity from the persistent information (which can vary easily later on). Such a design is superior as it allows to inject the correct data access object to the Resource entity (and it also means that it will be much more testable). Also, it allows to have multiple DTOs, for example: one for persistency and one for visualization.

In order to derive a PersistentResourceDTO from a Resource entity I will use an AutoMapper library.

AutoMapper uses a fluent configuration API to define an object to object mapping strategy, thus allowing easy transformations.
Here is the PersistentResourceDTO declaration:

[Serializable]
public class PersistedResourceDTO
{
public Uri Uri { get; private set; }
public byte[] Content { get; private set; }
public DateTime DateCreated { get; private set; }
}

Using AutoMapper library is especially easy when the properties and methods of the source type match to the properties of the destination type - this is called flattening.
Thus ExtractPersistentDTO method's implementation is simple and coherent.

private PersistedResourceDTO ExtractPersistentDTO()
{
// creates a mapping between Resource and persistent Resource DTO.
Mapper.CreateMap<Resource, PersistedResourceDTO>();
// flattens the current Resource object into PersistedResourceDTO.
PersistedResourceDTO dto = Mapper.Map<Resource, PersistedResourceDTO>(this);

return dto;
}

AutoMapper library also allows to project a mapping. Projection - transforms a source to a destination beyond flattening the object model. Consider that a Resource also has a collection of keywords. In order to visualize the Resource we want to use the following VisualResourceDTO where the title will be a combination of all the keywords.

[Serializable]
public class VisualResourceDTO
{
public Uri Uri { get; private set; }
public string Title { get; private set; }
}

Here is how to do it using the AutoMapper:


private VisualResourceDTO ExtractVisualDTO()
{
// creates a mapping between Resource and Resource DTO
Mapper.CreateMap<Resource, VisualResourceDTO>()
.ForMember( d => d.Title,
op => op.MapFrom(resource =>
string
.Join(" ", resource.Keywords.ToArray()))
);
// projects the current resource object into VisualResourceDTO
VisualResourceDTO dto = Mapper.Map<Resource, VisualResourceDTO>(this);

return dto;
}

(Remark: In the post above I didn't discuss other approaches, like ORM solutions).

Sunday, October 4, 2009

Notes on C++/CLI

(Cross post from IRefactor)
If you asked for my opinion whether to develop an application using (unmanaged) C++, I would strongly advise you to reconsider.

Unless you deal with real time applications (or near real time applications), you should better utilize the managed world. Sure, there are times for old good C++; especially when the application's memory footprint is an issue, but needless to say, you have better chances in productivity, ease of development and maintainability in the managed applications (C#, Java and etc...) than in the unmanaged world.

Sometimes, obviously, the above advice is impractical. When dealing with complex algorithmic issues, which already have pretty sound support in various unmanaged C++ toolkits and frameworks, you are forced to choose what exists over reinventing the wheel.

C++/CLI can bridge the gap.
The common practice is to wrap the unmanaged libraries with the C++/CLI, thus exposing the unmanaged functionality through the managed C++ layer. In the example below, Taxes project contains various algorithms for tax calculations written in (unmanaged) C++. The Taxes project is wrapped with TaxesMixed project which is a C++/CLI project. Finally, TaxesApp project, which is written in C#, uses the TaxesMixed wrapper to utilize the complex unmanaged tax calculations.


Tipical Solution

When dealing with unmanaged, mixed (C++/CLI) and managed projects, there are some notes to keep in mind:

Debugging

If you want to debug the unmanaged code (e.g.Taxes above) from the managed (e.g. TaxesApp above), don't forget to mark the option enable unmanaged code debugging on the debug tab of the managed project's settings.


Enable unmanaged debugging tab

Implementing Destructor/Finalizer

C++/CLI classes that use unmanaged C++ classes should implement Dispose\Finalize pattern (look for: "Deterministic finalization template" title). Apparently, implementing the pattern is much easier using C++/CLI than C#. All you need, is to provide a deterministic destructor (~ syntax) and a finalize method (! syntax) and everything else will be generated by the C++/CLI.


TaxesMixed::TaxCalculatorWrapper::~TaxCalculatorWrapper()
{
this->!TaxCalculatorWrapper();
}

TaxesMixed::TaxCalculatorWrapper::!TaxCalculatorWrapper()
{
if(nullptr != m_Calculator)
{
delete m_Calculator;
}
}
C++/CLI will generate all the additional Dispose, Dispose(bool) and Finalize methods in order to complete the pattern.


Here is a quick peek into the Dispose(bool) method, using Reflector.
As you can see, the method calls the deterministic Dispose method (~) when the TaxWrapper.Dispose() method is called and calls the Finalize method (!) when the TaxWrapper is garbage collected.



To pin or not to pin?

When a pointer to a managed object (or its part) needs to be passed to the unmanaged code, there is one important issue to be aware of:
Managed objects (on CLR Small Object Heap) don't remain at the same location for their lifetime as they are moved during the GC heap compaction cycles.
As a consequence,a native pointer that points to a CLI object becomes garbage once the object has been relocated. In order to ensure a correct behavior, C++/CLI introduces a pin_ptr pointer which pins a CLI object in order to prevent its relocation while a garbage collection cycle occurs.

(If you need a pointer semantic in C++/CLI you can use an interior_ptr pointer which is updated automatically when a garbage collection cycle occurs and remains a valid pointer even after the compaction.)

You declare a pin_ptr as follows:

pin_ptr<type> = &initializer;
Example:

public class Person
{
public string Id {get; protected set;}
public double[] Taxes { get; protected set;}

public Person()
{
Id = "SSN:12345"
Taxes = taxesDal.Load(this.Id);
}
}

void TaxesMixed::TaxCalculatorWrapper::CalculateAnnualTaxes(Person^ person)
{
//Pinning a whole object.
pin_ptr<Person^> ptr = &person;
//Passing the object or one of its value members to a native code.
. . .

//Pinning an array (by pinning the first element).
pin_ptr<double> arrPtr = &person->Taxes[0];
//Assigning to a native pointer
double* arr = arrPtr;
. . .
}
When dealing with pin_ptr you should remember:

  • Pinning a sub-object defined in a managed object has the effect of pinning the entire object.
  • Pinning an object also pins its value fields (that is, fields of primitive or value type). However, fields declared by tracking handle are not pinned.
    (To avoid redundant mistakes, my suggestion is to always pin the required reference type member, thus pinning the whole object.)
  • A pinning pointer can point to a reference handle, value type or boxed type handle, member of a managed type or to an element of a managed array. It cannot point to a reference type.
In any case, if you are interested in reading more about C++/CLI, you can find here very good tutorials on the topic.