Multimethods in .Net

July 23, 2009

Today i was browsing through the wikipedia, and explored various programming concepts that i am still not even heared of.

One of those is multimethods, or multiple dispatch. Multiethod is a method, which is invoked dynamically based on it’s arguments. AFAIK, what I mostly use is inheritance, which forces to dynamically select the required method at runtime based on the object type. However, arguments are not involved in this process, they are checked at compile time.

Multimethods are also compared to a Visitor pattern. While this pattern achives the same result, it carries it’s own dissadvantages. Here is a nice explanation of Visitor vs MultiMethods

What is most interesting, is that .Net does not support these out of the box, but there is a library which does just that. Take a look at MultiMethods.Net

There is an interesting “debate” going in Ayende’s reply about “Analyzing NH 2.1 Changes”. The biggest point of this discussion, IMO, is this statemen made by Patrick Smacchia:

(NHibernate) code base is completely entangled and it must be a daily pain to maintain the code”

This is really a strong argument, which must be backed by a lot of facts. Apparently, in the long discussion a lot facts and different view points all got mixed up. So I will try to highlight some of the more interesting points that caught my mind. So the story goes like this

The statement about NHibernate entanglement is supported by the fact, that a lot of namespaces are using each other. This is very well  illustrated by this image. Both Mark and Patrick agree that namespaces are the right thing to measure coupling.

> Mark Lindell asks Ayende: Are you claiming that using either namespaces or assembly dependencies is not valid for the NHibernate code base?

> Patrick: On this I follow Mark Lindell: If you don’t use namespaces to componentized and create layer inside your unique assembly then which other concrete artifact are you relying on?

Ayende responds:

-> Ayende: Analyzing namespace dependencies as a way to measure coupling isn’t going to work for NH, no.

> Ayende: (NHibernate) is highly componentized, and we are actually working on making this even more so, by adding additional extension points (like the pluggable proxies, object factories, and more).

Patrick then argues, that NHibernbate is not componentized from the inside (as seen by NHibernate developers, that is). I believe this means that Patrick agreed, that NHibernate.dll can be treated as single component from the user perspective, as he did not object it. If we look at NH as a component, then this is the standard stuff that is needed to use NHibernate:  NHibernate.Cfg.Configuration, ISessionFactory, ISession.

Patrick argues, that it would be difficult for a newcomer to start working on NH:

*Patrick Smacchia: But you say it is highly componentized from the user point-of –view, not from the NHibernate insider point-of –view. Think of the new developers coming on NHibernate. How can he understand what depends on what and why?

Ayende’s answer was that a new person has joined NH last year and brought a new feature, that is a ANTLR HQL parser, which resulted at least single nice feature, such as bulk actions.  Another argument was a number of patches sent by users. Those patches are relevant and applied.

Patrick then goes to say, that you have to somehow grasp the intentions of the former developers. He does not point how to do that, however

> Patrick: Because if one cannot recover the mental state of the former developer, then one is about to miss former developer intentions. If one doesn’t understand former intentions, one cannot do better code than it was.

Ayende gives two ways how this is working in NH.

> Ayende: If I can’t understand what is going on from the code, it is a problem in itself, period.

> It is actually _really_ hard to break NHibernate, we got pretty much the entire thing covered every which way.

So basically I see there two assumptions, each held by the other side:

  • One assumption is that “each namespaces depends directly or indirectly on all other namespaces”. Which constitutes “must be a daily pain to maintain the code. There is a total lack of componentization and each modification might potentially affect the whole code base.”
  • And other assumption is – NH does not use namespaces as way to componentize the system. NH namespace dependancy does not make the point, that it is a pain to maintain the code. However, huge unit test coverage makes it difficult to breake existing features and it is imperative that a programmer understands the code and is able to make it better (even with namespaces beiong not used to componentize the system)

I believe the reader can see that both parties have very good points, but one or another just don’t want to embrace the fact, that what works in one place, does not work in another. That goes even for all the rules made or discovered by human. While Newton mechanics works on Earth, they do not necessarily work with bigger or smaller scales.

Everything is dependent on the context, though, even Frans Bouma would like to disagree with me. While one great practice might work in one place, in another it might just fail.  There is no “one size fits it all”, and there is no silver bullet. So I would disaggre with Frans Bouma and would say that Principles aret bound to context.

One final thing about understanding code: Boxes and arrows help to get an abstract view of a system, especially when you need to get a first glance and see the big picture. However, it does not help when you try to understand how one box interacts via some dotted arrow with another arrow.  Unfortunately, many of the things are in the details (though not completely all, of course). The main point here is that a developer must have a very strong thinking capability. He / she has to be able to keep in mind all the boxes and arrows mentally. If a developer can not develop a mental model easily and navigate it easily by simply looking at the code, then he will be in a difficult position. I would go even up to the point saying that ability to relate code to diagrams, ability to relate code to business requirements, or code to mental model is a must. This is the point that distinguishes one developer from another. To sum up, namespaces  dependency do not necessarily show code entanglement, but i believe this information can and must be used to evaluate the code based on the given context

There are many new features, read the full list here

Here is the official post. Download and enjoy bulk actions and dependency injections :)

Yesterday I was upgrading NHibernate to a 2.1.x branch, which will be the next release in the comming months.

The upgrade process was not that extremely difficult, but it was really complex and rather long, as i am using Castle project and NHibernate.Generics

So the overal process was like this:

  1. Checkout Castle trunk, and build it.
  2. Update Castle.DynamicProxy2 and Castle.Core references in NHibernate
  3. build NHibernate
  4. Checkout NHContrib project
  5. Build NHibernate.Search project, which is part of NHContrib. Don’t forget to update references.
  6. Build NHibernate.Linq project, which is also part of NHContrib. For this project i had to use SharpDevelop, since it does not support nant. But everything works nice and clean as usual :)
  7. Update references in Castle project. These were in \SharedLibs folder. And NHibernate.Linq reference was in \SharedLibs\net folder
  8. Successfully build everything with nant
  9. Build NHibernate.Generics

Note that for NHibernate and Castle you have to compile against 3.5 paltform, but the generated assemblies can run on .Net 2.0.   This is done by passing an argument -t:net-3.5  to nant.

So after building everything, had to add proxyfactory.factory_class configuration variable, as described here. Pay  close attention to the fact, that a class assembly is uniquely identified by both it’s name, and it’s assembly name. Since i am using castle, i had to add this line:

property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>

That’s it.  Now i have bulk actions capability and “group by” by IProjection :)

Today I got a strange error.

Error CS0518: Predefined type ‘System.Object’ is not defined or imported

Strangely, all nant related tasks just work as accepted.

After a little googling i’ve found a solution here, that says that i need to reference mscorlib. I did that and the error was gone.

Then I opened my project preferences and saw that a checkbox was check, which told not to reference mscorlib. After unchecking the checkbox, the day was saved.

do not reference mscorlib

The screenshot shows preferences in SharpDevelop 3.1

How would you go about implementing this kind of functionality:

After changing a domain property, a system function is called. If it triggers another property, other system functions are called, if there are any.

A domain property is just any property, that has a business meaning, for example a person has a Name and Surname, a task object has a collection of ResponsibleUsers, and Status, and FinishDate, etc.

A system function is a custom business logic, that can be implemented either by a programmer, compiled and loaded during system start up, or it might be defined via “Administration” menu in your application.  In any case, this system function is registered for a concrete business type, and some exact property.

An example might look like this:

[OnPropertyChanged(typeof(Task), “Status”)]

public void OnStatusChange(Task task)

{

if (task.Status.Name.Equals(“Finished”))

task.FinishDate = DateTime.Now;

}

[OnPropertyChanged(typeof(Task), “FinishDate”)]

public void OnFinishDateChange(Task task)

{

// do something with FinishDate property

}
Manually implementing INotifyPropertyChange for each of our domain object is not a solution. What i would go with is an automatic solution.

One nice source of ideas is FabioMaulio and José F. Romaniello blogs.

Here are the blog posts that are very very interesting:

All these posts together tell how to dynamically inject necessary functionality into your POCO via interceptors, and how to wire everything with NHibernate.

As a side result, it also tells how to programme even without POCO, that is only with interfaces of your domain entities.