5

Further to this question:

Composition over Inheritance - where do extra properties go?

The accepted answer and similar ones answer this nicely. But to take this further, what if the Sales department and Production department wanted to record different information about Sickness and Holiday absences? This could be one solution:

public class Holiday : Absence
{
    //Extra fields go here.
}

public class Sickness : Absence
{
    //Extra fields go here.
}

public class SalesHoliday : Holiday
{
    //Extra fields go here.
}

public class SalesSickness : Sickness
{
    //Extra fields go here.
}

public class ProductionHoliday : Sickness
{
    //Extra fields go here.
}

public class ProductionSickness : Sickness
{
    //Extra fields go here.
}

clearly, this is the start of a class explosion which will only get worse, and therefore should be avoided.

One possible solution would be to use the Decorator Pattern (Gang of Four). This would be ideal but in this hypothetical example, the persistence is with NHibernate. I have looked all over the place for an example of how to map the Decorator pattern in NHibernate and not found anything. My experiments have, and one point, utilised various combinations of subclass mappings, joined-subclass mappings, union-subclass mappings, discriminators, implicit polymorphism and many-to-any mappings, but so far with no satisfactory results. Has anyone cracked this one? An Employee entity would have a collection of absences of any type so polymorphic behavior is a requirement.

Community
  • 1
  • 1
Paul T Davies
  • 2,527
  • 2
  • 22
  • 39

2 Answers2

3

In modeling this particular type of application I would try to stay away from sub-classing an absence based on department. Instead, I would try to make the absence handling system capable of supporting any department. You can devise a model that allows adding custom properties to an absence if that becomes necessary. This could be done using either a generic notes field or a dictionary. This data could then be further structured by a given context, such as Sales and Production.

One way to think of this is that an absence in the sales department is much like an absence in the production department, so the 'type' of the entity does not change. What may change is particular details about an absence, which in turn warrants the composition over inheritance approach.

eulerfx
  • 36,769
  • 7
  • 61
  • 83
  • What about NOT this particular application? I think that other also try to do decorator with NHibernate. Any ideas? 10x. – mynkow Jul 19 '11 at 07:11
  • 1
    Thanks eulerfx, but my question was not about coming up with a solution to this scenario. The question was about implementing a decorator pattern in NHibernate, and this scenario was an example. There are many situations where a Decorator would be a perfect solution but the NHibernate mapping caused problems. Also your suggestion of storing proerties in a dictionary is not a good one. I have been tempted by this in the past and it leads to nothing but trouble. Surely this is a classic anti-pattern? Thank you for taking the time to answer but I'm not sure why this has received so many upvotes? – Paul T Davies Jul 19 '11 at 09:24
  • @Paul T Davies: I guess I did not see how decorator pattern would apply here. In general, I think the decorator pattern can be mapped in NH by mapping the decorated component as usual, and then have the repository create the decorator passing the component into it. Conversely, the repository would extract the decorated component when needed. – eulerfx Jul 19 '11 at 20:33
0

I finally answered my own question. Union-subclass is the way forward, like in this pizza example:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="Decorator.Domain.Entities"
                   assembly="Decorator.Domain">
  <class name="IPizza" abstract="true">
    <id name="Id" column="Id" type="guid">
      <generator class="assigned"/>
    </id>
    <many-to-one name="Order" class="Order" column="`OrderId`" cascade="save-update" />

    <union-subclass name="Pizza" table ="`Pizza`" >
      <property name="Size" column="`Size`" />
      <property name="Cheese" />
      <property name="Tomato" />
    </union-subclass>

    <union-subclass name="PepperoniDecorator" table ="`PepperoniDecorator`" >
      <many-to-one name="BasePizza" class="IPizza" column="`BasePizzaId`" cascade="all" />
      <property name="ExtraSpicy" column="`ExtraSpicy`" />
    </union-subclass>

    <union-subclass name="OliveDecorator" table ="`OliveDecorator`" >
      <many-to-one name="BasePizza" class="IPizza" column="`BasePizzaId`" cascade="all" />
      <property name="Colour" column="`Colour`" />
    </union-subclass>
  </class>
</hibernate-mapping>

I go in to this in more detail on my blog:

http://lucidcoding.blogspot.co.uk/2013/07/mapping-decorator-pattern-in-nhibernate.html

Paul T Davies
  • 2,527
  • 2
  • 22
  • 39