Ayende @ Rahien

Refunds available at head office

What makes Boo a great language

I really like the CLR. It is a great platform, it has a rich set of libraries, it has a lot of power and flexibility, and it was designed with multi language support in mind, which means that what you can do on the CLR vs. what you can do in your language are two different things.

It is just too bad that the default CLR language is C#. Now, that probably raised a few brows, and definitely some hackles. C# is a great language, I can hear you saying. Well, yes, sort of. If you thinks that holding the compiler’s hands is a useful thing to do. Leaving aside the ability to extend the compiler, Boo has the following to offer us:

Syntactic sugar for common programming patterns - List, hash and array literals, object initialization, string formatting and regular expression matching are all first class concepts in Boo, with direct support for all of them in a natural manner.

Automatic Variable Declaration together with Automatic type inference – the compiler takes care of things for you, instead of having to type the same thing over and over and over again. Some would say that this is bad, for them I would reply that they should try it first. It works.
Take a look at this:

def random():
	return 4 # selected by dice roll, guaranteed to be random
val = random() 

Is there are reason that I would need to specify the type over and over again? The compiler can figure it out for itself and not bother you with it. If you want to get a compiler error, you can:

val as string = random() # will error about type mismatch 

Automatic type casting – don’t make me explicitly say it, figure it out for me. I’ll have unit tests to check to cover me.

Duck typing – Boo is a strongly typed language, but you can ask the compiler to relax those constraints at certain scenarios. It makes some things much more natural, especially since you have a way to get into this infrastructure and decide what to do at runtime.
If we will take a simple example, let us look at the XmlObject and what we can do with it:

person = XmlObject(xmlDocument)
print person.FirstName
print person.LastName 

What we just did was resolve, at runtime, that we were asked to get the value of a property called “FirstName”, and we did. This is a trivial piece of code to implement.

Just those benefits present a significant improvement in the language experience, and we haven’t even touched the extensible compiler yet.

The Boo Language

So, what is this Boo language anyway? I am talking about it fairly often, but I never explained, and I am going to assume that people aren't following links :-)

image Boo is an object oriented, statically typed language for the common language runtime with a Python inspired syntax and focused on language and compiler extensibility.

Boo is an Open Source project, released under the BSD license. This means that you are free to take, modify and use the language and its products in any way you want, without any limitation[1]

. Rodrigo B. de Oliveira started the project, and since then grown in popularity. The project is active and continually evolving. At the time of the writing, the released version of Boo is 0.8.

However, Boo seems to be following the trend of many open source projects, in that that it is not really rushing toward 1.0 release. Boo has been around for a number of years, and I have been using it for production for the last two years.

Production, in this case, means systems that move money around with my neck on the line. I have a high degree of trust in it, obviously.

Beyond being a really malleable language, suitable for DSL. Boo is also a nice language to work with for day-to-day tasks. The SharpDevelop IDE project has support for Boo, so you get the usual benefits. There is an ongoing project to support Boo in Visual Studio, and I have an active interest in seeing support for that being established. I don't much care for which IDE, but I want a standard, checklist driven way of getting a language running.

Here is a secret, I tend to think and write in Boo, translating down to C# because I have to. Boo is a far more flexible language, and the ability to reprogram the compiler makes tedious tasks in other languages an amusing challenge. Those same tedious problems are usually overcome, to some degree, by throwing code generation at the problem until it goes away.image

In Boo, we would usually tell the compiler how we want to handle this, and let the compiler take over from there. This is similar to code generation, except that this is done at the compiler level, which means that we have far more knowledge about what is going on.

For example, let us say that we want to implement the singleton pattern. We need to do quite a bit of work to make it happen. Ensure that creating the singleton is thread safe, lazy initialization, make all the constructors private, ensure that serializable singleton remain singleton through serialization/deserialization, create static Instance property, have no static members on the singleton class.

To do this in most language we would have to follow an implementation pattern and write fairly repetitive code. In Boo, we can capture this usage pattern in an AstAttribute (more on that later) that will do all of that for us, at the cost of a single attribute declaration.

Similar capabilities allow correct usage of disposable, observable, and more advance techniques such as aspect oriented programming.

Some of the capabilities that Boo has can be had using IL Weaving tools such as PostSharp. The problem with those is that using them is something that happens after compilation. As a simple example, you would not be able to create a singleton in this manner, because you would not be able to generate the Instance property at the appropriate time.

Assuming that you want to use the singleton in the same assembly as it was defined, you will not be able to reference the Instance property, it will not exist until the post compile step has run. Boo, however, does this at compile time, so by the time the compiler get to the point where it is resolving the property, it has already been added.

In short, I really like the language and what it allows me to do.


[1] Well, if you are interested in creating a new language called Ba, you probably would want to make it clear where the project ancestry came from…

On the faults of thinking: It is extensible, the users can add this

Two posts and a discussion yesterday has finally made it clear what my stance in regards to extensibility is. Extensibility is well and good, but if I need to extend a product from the get-go, just to get the basic functionality going, then this product blew it.

The discussion that I had was about SSIS and the need to create a DateParserComponent. Basically, a wrapper around DateTime.ParseExact(). I don't mind the work in creating it, but it is very telling that this is something that you would need. The posts that help cement this thinking were Phil Haack about Convection Controller and Ivan's Filters implementation for the MS MVC framework.

Let us start by saying that neither posts has code that I can take to production, and that is explicitly state in the posts. Demo code is demo code, after all.

Nevertheless, I am going to talk about this demo code, and its implications. Phil has posted this Convention Controller as a way to show how easy it is to extend the MS MVC framework. The problem with that this is showing how to extend the MS MVC framework for demos. The code required to make this run for production is far more complex*.

Production code has to be reliable, performant, stable, etc. A lot of effort goes into taking a piece of code from the proof of concept stage to the ready to production stage.

I believe that extensibility is extremely important. But that to answer of "you can extend the product" for any core scenario is nothing but blame shifting. I mean, Date Parsing in an ETL tool? Can you really consider that as a noncore scenario?

Now, in order to avoid the hordes of people that this will offend. I want to make one thing clear, convention controller is not a core scenario for the MS MVC framework. That is a by design choice of them that I disagree with, but that is the way it is.

We now begin to see a lot of the MonoRail stuff appearing on the MS MVC side, Rescues, Filters, etc. I hope that most of them would end up with the core product, but MS has stated the MonoRail feature parity is not a goal.

Just keep this in mind the next time that you are going to say "it is extensible, do this", you really ought to consider whatever this is an answer that is driven by the product's core scenarios vs. moving the work that should be yours to someone else's hands.

* This post is not about the convention controller, but to foretell the usual nitpickers, reflection is slow. Using un-cached reflection in a hotspot is a bad idea, even cached reflection is inappropriate at times.

OSS Chat logs:

[friend] says: I think maybe we should at least provide something as simple as MR
[friend] says: sorry I mean RoR
Ayende Rahien says: I hereby grant you permission to do that
Ayende Rahien says: send us a patch

Tags:

Published at

We'll just code-gen our way out of here

First, we have the implementation of the SendPropertyChanged method, can you spot the bug?

protected virtual void SendPropertyChanged(String propertyName)
{
	if ((this.PropertyChanged != null))
	{
		this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
	}
}

Then, you have:

public string CustomerID
{
	get
	{
		return this._CustomerID;
	}
	set
	{
		if ((this._CustomerID != value))
		{
			this.OnCustomerIDChanging(value);
			this.SendPropertyChanging();
			this._CustomerID = value;
			this.SendPropertyChanged("CustomerID");
			this.OnCustomerIDChanged();
		}
	}
}

And this:

public Customer Customer
{
	get
	{
		return this._Customer.Entity;
	}
	set
	{
		Customer previousValue = this._Customer.Entity;
		if (((previousValue != value) 
					|| (this._Customer.HasLoadedOrAssignedValue == false)))
		{
			this.SendPropertyChanging();
			if ((previousValue != null))
			{
				this._Customer.Entity = null;
				previousValue.Orders.Remove(this);
			}
			this._Customer.Entity = value;
			if ((value != null))
			{
				value.Orders.Add(this);
				this._CustomerID = value.CustomerID;
			}
			else
			{
				this._CustomerID = default(string);
			}
			this.SendPropertyChanged("Customer");
		}
	}
}

Both properties show exactly why I despise code generation as an architectural approach.

Instead of taking the appropriate route, and actually solving the problem at hand, they just threw code at it until it looked like it worked.

Throwing a DSL over the wall

Here are a few thoughts about the idea that given a DSL, you can just turn your entire business related stuff to the business users, and be done with it. This kind of thinking is very common, from the dreams of the secretary building applicaitons by dragging boxes to the business analyst modifying the workflows.

I disagree with this quite strongly. Giving a user this type of tool is an irresponsible step at best. The users are not developers, and they will make mistakes. And the first time that the business will lose money over it, it will be your fault.

  • It will be your fault when the server is on 100% CPU because the user has created endless loop.
  • It will be your fault when the server is down because of stack overflow.
  • It will be your fault that Mike from accounting made "just a tiny modification" that suddenly means that you sold a product with for 50% less than you paid for it.
  • It will be you fault that Joe just got a paycheck proudly stating -43.9.
  • It will be your fault that the company baught the entire fish market for the next three years.
  • It will be your fault that no one has any idea what the company's own business processes are.
  • It will be your fault that the database contains incosistent data.
  • It will be your fault that there is not control over it.
  • It will be your fault that there hasn't been an audit log for the last three months.

It will be your fault

Handing a user a tool like that is wonderful, it is a tool that can enable better communication and rapid response betweenthe IT and the business. Having a DSL means that you are talking in the same language, that you are less likely to mess up because of translation problems.

It does not mean that you can just throw it over the wall and walk away. A DSL is code, and like all code, it requires code review, QA, change management (source control), testing, intention revealing semantics, perf testing, auditing, error handling, transaction handling and much more.

Professional developers are having problems with handling that, giving it to unexperienced users is a mistake. It might work for the first few, but this is not a sustainable approach.

Consider the departmental application and their usual bar of quality. Do you truly intend to bring that, knowingly, into your codebase?

Requirements of a DSL engine

Getting a DSL to work for a single file is fairly easy. Getting it to work in a real application is much harder. There are quite a few scenarios that you need to deal with irrespective of the DSL itself.

Those issues include:

  • Caching - compilation is expensive
  • Batch compilation - see above, also very important
  • Error handling - we can probably do at least some work here to make it easier. At the very least, output something like compilation exception would give us the nice yellow page with the error, compiled output, etc.
  • Automatic refresh - when the file changes, we can invalidate the cache and load from the file again.
  • IoC integration ?

What else do you think is needed?

Don't like visibility levels, change that

This came up with respect to MS MVC. The MS MVC team has decided to make some methods protected, and that makes testing using Rhino Mocks a bit of a pain.

Let us assume that I want test that the call to ProductController.Index() will render the "index.aspx" view. I can do something like:

[Test]
public void ShouldAskToRenderTheIndexAspxView()
{
	MockRepository mocks = new MockRepository();
	ProductController controller = mocks.PartialMock<ProductController>();
	using(mocks.Record())
	{
		controller.RenderView("index.aspx"); // <<-- Compiler error here, RenderView is protected!
	}

	using (mocks.Playback())
	{
		controller.Index();
	}
}

Problem, part of the Rhino Mocks design goal was the use of the compiler and tools as verifiers. I explicitly do not want to have strings in my code, and I put them only where I have no other choice. However, since Rhino Mocks by runtime subclassing, there is no issue with reflection calls...

This means that we can get around this limitation by using the following extension method:

public static void RenderView(this Controller self, string action)
{
	typeof(Controller).GetMethod("RenderView").Invoke(self, new object[] { action} );
}

This is it, it will compile and work now.

DSL & IoC - Combining powerful concepts

I was just writing this line of code:

DslExecuter<SchedulingDslEngine>.Create(“validateWebSiteIsUp”)

When it occurred to me that this looks a look like an IoC resolve call. Which got me thinking about combining both concepts together, which gave me the shakes.

The idea is that we can expose those dependencies like this:

customers as ICustomerRepository
fraudService as IFraudService
alerts as IAlertService

for customer in customers.FindAll(With.Orders):
	for order in customer.Orders:
		if fraudService.IsFraud(order):
			alerts.ForFaurdOn(order)
			if customer.Important:
				alerts.NotifyCustomerAboutFraud(customer)

Leaving aside the mountain slope code*, consider what is going on here. We are exposing dependencies by specifying the types that we need. We can then get them through the IoC and execute the code in hand.

This means that the DSL has full access to everything in the application, and is subject to the same rules and behavior as all the other components. From my point of view... sweeeeeet.

* First example that popped to mind, yes, I know it is a bad one.

Javascript, lexical scopes and what your momma thought you about variables

Let us assume that we have this amazing javascript function:

function test()
{
	var nums = [1,2,3,4,5,6,7];
	for(var i = 0; i<nums.length; i++)
	{
		var alertLink = document.createElement("A");
		alertLink.href = "#";
		alertLink.innerHTML = nums[i];
		
		if( nums[i] % 2 == 0)
		{
			alertLink.onclick = function() { alert('EVEN: '+ nums[i]); };
		}
		else
		{
			alertLink.onclick = function() { alert('ODD: ' + nums[i]); };
		}
		
		document.firstChild.appendChild(alertLink);
		document.firstChild.appendChild(document.createElement("BR"));
		
	}
}

Can you guess what it would generate? Quite a few undefines alerts, as a matter of fact. Why is that? Because the anonymous function is a closure, which capture not the value of i, but the i variable itself.

This means when we click on a link that this method has generated, we use the last known value of i. Since we have exited the loop, i is actually 8.

Now, in C# we have the same problem, and we can solve it by introducing a temporary variable in the loop, so we change the code to look like this:

	
function test()
{
	var nums = [1,2,3,4,5,6,7];
	for(var i = 0; i<nums.length; i++)
	{
		var alertLink = document.createElement("A");
		alertLink.href = "#";
		alertLink.innerHTML = nums[i];
		
		var tmpNum = nums[i];
		
		if( nums[i] % 2 == 0)
		{
			alertLink.onclick = function() { alert('EVEN: '+ tmpNum ); };
		}
		else
		{
			alertLink.onclick = function() { alert('ODD: ' + tmpNum ); };
		}
		
		document.firstChild.appendChild(alertLink);
		document.firstChild.appendChild(document.createElement("BR"));
		
	}
}

Try to run it, and you'll get an.. interesting phenomenon. All the links will show tmpNum as 7. Again, we captured the variable itself, not its value. And in JS, it looks like you are getting the same variable in the loop, not a new one (this is absolutely the wrong way to describe it, but it is a good lie), like you would in C#.

What is even more interesting is that you would get the exact same result here:

	
function test()
{
	var nums = [1,2,3,4,5,6,7];
	for(var i = 0; i<nums.length; i++)
	{
		var alertLink = document.createElement("A");
		alertLink.href = "#";
		alertLink.innerHTML = nums[i];
		
		
		if( nums[i] % 2 == 0)
		{
			var tmpNum = nums[i];
			alertLink.onclick = function() { alert('EVEN: '+ tmpNum ); };
		}
		else
		{
			var tmpNum = nums[i];
			alertLink.onclick = function() { alert('ODD: ' + tmpNum ); };
		}
		
		document.firstChild.appendChild(alertLink);
		document.firstChild.appendChild(document.createElement("BR"));
		
	}
}

Here we have two different lexical scopes, with respectively different variables. Looks like it should work. But the lexical scope of JS is the function, not the nearest set of curly. Both tmpNum refer to the same variable, and as such, are keeping the last value in it.

If the lexical scope is a function, we need to use a function then. Here is a version that works:

	
function test()
{
	var nums = [1,2,3,4,5,6,7];
	for(var i = 0; i<nums.length; i++)
	{
		var alertLink = document.createElement("A");
		alertLink.href = "#";
		alertLink.innerHTML = nums[i];
		
	
		if( nums[i] % 2 == 0)
		{
			var act = function(tmpEVEN)
			{
				alertLink.onclick = function() { alert('EVEN: '+tmpEVEN); };
			};
			act(nums[i]);
		}
		else
		{
			var tmpODD = nums[i];
			alertLink.onclick = function() { alert('ODD: ' + tmpODD); };
		}
		
		document.firstChild.appendChild(alertLink);
		document.firstChild.appendChild(document.createElement("BR"));
		
	}
}

And that is it for today's JS lesson.

The consequences of web services architecture

I mentioned before that MS CRM's decision to build all its external API based on web services (that cannot be accessed outside of ASMX proxies) was a big mistake. It is a mistake because you are handing the developer a really clumsy, stupid, API.

I just spent an hour trying to figure out how to set a value to null. An hour!

It couldn't be as simple as this:

customer.new_employeeintouch = null;

It has to be:

customer.new_employeeintouch = new Lookup();
customer.new_employeeintouch.IsNull = true;
customer.new_employeeintouch.IsNullSpecified = true;

Building an External DSL

Over in the Alt.net mailing list, Glenn said:

If I was really being verbose in the way a business user would expect to define this I would say

               When customer is preferred and the order exceeds 1000 then apply a .05 discount and apply free shipping.

Now do that in a DSL….

Now, I am sucker for this kind of things, and I can probably use the practice. So I decided to go ahead with this. Just to be clear, this is supposedly a natural language processing, only we are going to cheat and get around that.

First, let us analyze the structure of the statement that we need to handle:

When customer is preferred and the order exceeds 1000 then apply a .05 discount and apply free shipping.

I put strike through all the fluff stuff, the things that doesn't really means anything for the language. Keywords are marked in blue, operators in red.

We have the following keywords:

  • When
  • And
  • Then

And the following operators:

  • Is
  • Exceeds
  • Discount
  • Shipping

Everything else is a variable.

This language follows the following syntax:

When [parameter] [operator] [value] (and [parameter] [operator] [value])+ then [parameter] [value] [operator] (and [parameter] [value] [operator] )

Note that the syntax between the when clause and the then clause is different. The operator is the last word there. This is because on the when we would usually do comparisons, while on the then we will perform actions.

Now, to the actual building of the language. We have the following model:

image

Let us take a look at the parser, it is a stupid, single purpose one, but it works. The main parts are to extract a list of ActionExpressions from the language.

public WhenThenClause SplitToWhenThenClause(string text)
{
	if (text.StartsWith("when", StringComparison.InvariantCultureIgnoreCase) == false)
		throw new InvalidOperationException("statement should start with a when");
	int thenIndex = text.IndexOf("then", StringComparison.InvariantCultureIgnoreCase);
	if (thenIndex == -1)
		throw new InvalidOperationException("statement should have a then");
	WhenThenClause clause = new WhenThenClause();
	string whenClause = text.Substring(4, thenIndex - 4).Trim();
	ParseClause(whenClause,
	            delegate(string[] parts)
	            {
	            	ActionExpression item = new ActionExpression();
	            	item.Left = parts[0];
	            	item.Operator = parts[1];
	            	item.Right = parts[2];
	            	clause.When.Add(item);
	            });
	string thenClause = text.Substring(thenIndex + 4);
	ParseClause(thenClause,
	            delegate(string[] parts)
	            {
	            	ActionExpression item = new ActionExpression();
	            	item.Left = parts[0];
	            	item.Right= parts[1];
	            	item.Operator = parts[2];
	            	clause.Then.Add(item);
	            });

	return clause;
}


private static void ParseClause(string clause,
                                Action<string[]> action)
{
	foreach (string subClauses in
		clause.Split(new string[] { "and" }, StringSplitOptions.RemoveEmptyEntries))
	{
		if (subClauses.Trim().Length == 0)
			continue;

		string[] parts = subClauses.Split(new char[] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries);
		if (parts.Length != 3)
			throw new InvalidOperationException("A clause should have three parts "+
"[object] [operation] [value], found:
" + subClauses); action(parts); } }

Now we need to look at the DslExecuter. This is the one that will take an ActionExpression and actually execute it. We are using reflection to avoid having to do all the work ourselves, so we have this:

public class DslExecuter
{
	private readonly Hashtable parameters = new Hashtable(StringComparer.InvariantCultureIgnoreCase);

	public void AddParameter(string name, object parameter)
	{
		parameters[name] = parameter;
	}

	public object Invoke(ActionExpression expression)
	{
		object obj = parameters[expression.Left];
		if (obj == null)
			throw new InvalidOperationException("Could not find parameter with name: " + expression.Left);
		MethodInfo method = obj.GetType().GetMethod(expression.Operator, BindingFlags.IgnoreCase 
| BindingFlags.Instance | BindingFlags.Public); if (method == null) throw new InvalidOperationException("Could not find method operator " +
expression.Operator + " on " + expression.Left); ParameterInfo[] methodParams = method.GetParameters(); if(methodParams.Length!=1) throw new InvalidOperationException(expression.Operator + " should accept a single parameter"); object converted; Type paramType = methodParams[0].ParameterType; if(paramType.IsEnum) { converted = Enum.Parse(paramType, expression.Right,true); } else { converted = Convert.ChangeType(expression.Right, paramType); } return method.Invoke(obj, new object[] {converted}); } }

Now that we have those two building blocks, it is very easy actually build the DSL itself. Here is the relevant code:

public void Execute()
{
	bool result = true;
	foreach (ActionExpression expression in parsed.When)
	{
		bool clauseResult = (bool) this.executer.Invoke(expression);
		result &= clauseResult;
	}

	if(result)
	{
		foreach (ActionExpression expression in parsed.Then)
		{
			executer.Invoke(expression);
		}
	}
}

We build a domain model to aid us here:

image

Basically this translate directly to the parameters that the DSL needs. This means that all we have left is just the setup of the DSL.

[Test]
public void CanExecuteThenStatement()
{
	ExternalDSLDemo dsl = new ExternalDSLDemo(sentence);
	Customer customer = new Customer();
	customer.CustomerStatus = CustomerStatus.Preferred;
	dsl.AddParameter("customer", customer);
	Order order = new Order();
	order.TotalCost = 5000;
	order.ShippingType = ShippingType.Fast;
	dsl.AddParameter("order", order);
	dsl.AddParameter("apply", new ApplyCommands(order));
	dsl.Execute();

	Assert.AreEqual(4750, order.TotalCost);
	Assert.AreEqual(ShippingType.Free, order.ShippingType);
}

But I am pretty sure that I explained that this external DSL are very hard. This doesn't seem very hard all.

No, this external DSL is not really hard. But try to do support something like:

when (customer is preferred) and (order exceeds 1000 or order is new) then ...

This is when it gets suddenly much more complex... and why I think that External DSL are rarely worth the time to fully develop them. It is much easier to build on top of an existing infrastructure.

You can get the code for this here:

https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/rhino-dsl/Rhino.DSL.Tests/ExternalDSL

Dogmatic? Who, me?

Jacob Proffitt calls me up to task for being inconsistent:

In this, Ole Friis is echoing the response I got from the intimidating Oren Eini when I suggested that TypeMock makes arguments that couple DI with unit testing go away.

The main weakness of Type Mock is its power, it allow me to take shortcuts that I don’t want to take, I want to get a system with low coupling and high cohesion.

Consenting AdultsThe implication is that he wouldn’t be developer enough to create a system with low coupling and high cohesion if he used powerful tools like TypeMock. Oren is inconsistent here because he’s otherwise all for developer empowerment as illustrated by his support for Jeffrey Palermo’s excellent post regarding treating developers as professionals.

How can I support the idea of alt.net as "running with scissors", responsible adults that are trusted to know what we are doing, with my comments on Type Mock having "too much power"?

It is a good thing that I never felt the need to be self consistent. It makes things much more... invigorating.

I'll start by saying that I often write bad code. What is bad code? In DevTeach, I showed James Kovacks a 150 lines methods that involved threading, anonymous delegates and exception handling in a ingeniously unmaintainable form. Bad as in you will get the axe and come after me with froth coming out of your mouth if you ever see it.

I have a certain style that works for me. It comes with a set of tools and practices that are built to encourage that style and mindset. Being a lazy bastard, I am careful to make sure that I cannot be too lazy, because otherwise it is usually me who needs to clean up my mess.

I believe that the choice of tool has a profound affect on my ability to work. That comes both at the tooling level (IDE, extensions, R#, etc) and the frameworks sides (IoC, OR/M, DSL, etc). Tools & frameworks should guide me where I want to go, and make it harder to do the wrong thing. This is a decision that I made based on my experience and observations.

After dealing with tools that do not encourage best practices, or tools that forces you to work harder to get there, it is a very important consideration to me. I don't see an inherent disconnect between the two. I believe that the term is that "with great power comes great responsibility". Recognizing that, I intentionally limit my own choices, in order to get things done using the approach that I believe is the best for what I am doing.

Does this mean that this approach is a one size fit all? Absolutely not.

In fact, I can tell you that from each and every project I come out with a profound understanding of how stupid I was when I got into the project, and how many mistakes I made in that project.

But, I do believe that this approach is applicable for a broad set of scenarios. Not all, but a broad set of scenarios.

I feel it in my waters

A few days ago I was listening to a recording of a design discussion, and I was at two minds about what was going on in my mind when I said some of the things that I said. I found myself in the odd position of both remembering my reasoning and listening to them as an outsider. It gave me some insight to the way I think. It is not really an analytical process.

There is a lot based on the taste of the idea. I am sorry, I am not sure how to express it in any other way. I decide on the idea/design based on how it feel. There was a lot of that in the discussion, for instance. I can usually explain my initial response when I give it some thought, luckily.

At one point there were about two minutes of failed design attempts, we can do X and then... hm, not that is too complex, so we will do Y which would... no, that doesn't handle the Foo requirement, etc.

It is partly preference, partly experience and partly the appliance of good habits learned from painful experiments.

Interesting experience...

Fuzzy smart selections

Not, I am not particulary hungry at the moment, despite what this image may suggest.

image  

Let us assume that I am hungry, and I would like some sort of a Vegetable to eat. Now, I know that I would really like to eat a carrot.

image

Problem.

I don't want to try all the possibilities in the kitchen. That would be real horror. But do I have any other choice? Assume that I have the time to do whatever I want, how would you handle the question of "give me something like carrot".

Please remember that simplicity is a value. And yes, I do have an idea about this.

DSL Styles - Imperative vs. Declarative

I posted yesterday about building a rule engine using a DSL. After I wrote that, I tried to think about what style it was. That made me realize that I had no clear distinction between imperative and declarative DSL. At least not a coherent, internally consistent one.

I asked the Alt.net mailing list, and a lively discussion enthused. Contrary to my opinion, a lot of people disagreed with my opinion that this is a declarative style DSL:

when User.IsPreferred and Order.TotalCost > 1000:
    addDiscountPrecentage  5
     applyFreeShipping
when not User.IsPreferred and Order.TotalCost > 1000:
suggestUpgradeToPreferred
     applyFreeShipping
when User.IsNotPreferred and Order.TotalCost > 500:
     applyFreeShipping

It looks too much like code apperantely. After some debate, we now have the following candidates for declarative DSL:

From Chad:

about User
       when Preferred and OrderTotal > 1000:
               Discount is 0.05
               And Shipping is FREE;
       when not Preferred and OrderTotal > 1000:
               Upgrade Suggested
               And Shipping is FREE;
       when not Preferred and OrderTotal > 500:
               Shipping is FREE;

Based on Berry's ideas:

applyDiscount 5.precent:
    when User.IsPreferred and Order.TotalCost > 1000
suggestPreferred:
     when not User.IsPreferred and Order.TotalCost > 1000
freeShipping:
     when Order.TotalCost > 500

The really interesting thing to me, so far, is that they are all functionality equivalents. From the point of view of the implementer, there isn't much difference at all betwee them.

My own, loosely defined and likely wrong definition was based on what the DSL actually did. If the DSL performed all the work internally, I would call it imperative. If the DSL performed some work that produced an object graph, which another part of the system would tehn consume, I would call it declarative.

Thoughts?

Complexity through good intentions

After I got some input from Scott Allen about my Rule Engine post, I took a look at PolicyActivity.

Take a look at the image, my commentary is below it:

image

Can someone please explain me who thought about this idea? When you get something like that, how are you supposed to actually look at this and figure out what is going on? You have no way to look at it and get an idea about what is going on in there. You have to go and look at those sub rules one by one.

For that matter, take a look at the text boxes here. You want me to write code there? There is actually intellisense on those text boxes, which scares me to no end.

How am I supposed to be able to get an idea on what is going on here? An overall view, not just inspecting a single leaf of grass at a time.

How am I to do code review on that? For that matter, how am I going to use source control with that. The answer, sadly, is again, binary source control. No diffs for you, nasty spoiled code driven developer. Take a look at this snippet.

<Rule.Condition>
	<RuleExpressionCondition Name="{p3:Null}">
		<RuleExpressionCondition.Expression>
			<ns0:CodeBinaryOperatorExpression Operator="ValueEquality">
				<ns0:CodeBinaryOperatorExpression.Left>
					<ns0:CodePrimitiveExpression>
						<ns0:CodePrimitiveExpression.Value>
							<ns1:Int32 >1</ns1:Int32>
						</ns0:CodePrimitiveExpression.Value>
					</ns0:CodePrimitiveExpression>
				</ns0:CodeBinaryOperatorExpression.Left>
				<ns0:CodeBinaryOperatorExpression.Right>
					<ns0:CodePrimitiveExpression>
						<ns0:CodePrimitiveExpression.Value>
							<ns1:Int32>2</ns1:Int32>
						</ns0:CodePrimitiveExpression.Value>
					</ns0:CodePrimitiveExpression>
				</ns0:CodeBinaryOperatorExpression.Right>
			</ns0:CodeBinaryOperatorExpression>
		</RuleExpressionCondition.Expression>
	</RuleExpressionCondition>
</Rule.Condition>

I actually had to cut some name space definitions from there, just to make it fit the screen.

Now, please guess what this translate to. Imagine a slightly more complex rule, and then try to do a diff on the changes when someone modify it.

I am waiting to be educated how this is a good thing.

Don't like the API, go ahead fix it, or not?

Over in the alt.net mailing list, Charlie Poole has said that he thinks that the Playback() method for Rhino Mocks would be better named Monitor().

Without thinking about it, I sent this reply:

public class CharliePreferences
{
     public static IDisposable Monitor(this MockRepository mocks)
     {
              return mocks.Playback();
     }
}

After I sent it, I started thinking about the implications. Both for legacy code and for preferences. I am not sure whatever this is a good approach is a good way to go. Thoughts?

A rule engine in less than 70 lines of code

As I continue to explore what we can do with DSL, I am getting more and more excited. Let us take a look at the following syntax:

when User.IsPreferred and Order.TotalCost > 1000:
    addDiscountPrecentage  5
    applyFreeShipping
when not User.IsPreferred and Order.TotalCost > 1000:
    suggestUpgradeToPreferred 
    applyFreeShipping
when User.IsNotPreferred and Order.TotalCost > 500:
    applyFreeShipping

The backend for that is a simple 68 lines class. Again, we had to extend the language to support the when keyword, but that is all we really had to do.

image

I tried to build the same using Windows Workflow, but I gave up after a few minutes. It was too much clicking, and not enough results.

It should look something like the image to the left, I assume.

From the perspective of maintainability and actually being able to look at what is going on, I know what I would like to have.

At any rate, you can get the backend here, and get the unit tests here. Both are part of the test suites of the Rhino DSL project.

To be frank, I can't believe how easy this stuff is.

 

.

Panic Attack

I went to sleep with the computer still playing. A few hours later, I woke up from a highly disturbing dream that I refuse to disclose, to find out that for the last hour or so, I have been hearing a WPF conversation. I'll leave any association between these two facts to the reader. But to top that, I found out that on VS 2005, I don't have ReSharper installed.

I had to run around like a headless chicken for a while, just to get to grips with that. Then I installed it again (removed previous version to install the EAP on VS 2008). I am feeling much better now, honestly. Now if I could only forget that dream...

My Startup Idea: Rocket Launcher

image

Taking advantage of a loophole in the export laws and some creative marketing, I am pretty sure that a startup to sell USB Nuclear Powered Rocket Launchers to petty tyrants is the next big thing.*

Wish me well, I now need to learn how to say I come in peace in Persian.

 

 

 

 

 

 

 

 

 

* This is a three level joke, if you don't get, don't worry, it is not intended to you.

Inverting Inversion of Control

What do you think about this code?

IoC.Container.Kernel.AddComponentInstance<IFoo>(this);
IBar context = IoC.Resolve<IBar>();//needs IFoo

For some reason it looks really funny to me.

More seriously, this is a good way to involve components that you cannot control in the container.

What should you test?

I just found myself writing this:

[Test]
public void When_resolving_using_framework_element_will_create_layout_using_resolver()
{
}

The code that I want to test looks something like this:

public void Register(FrameworkElement frameworkElement)
{
	Register(layoutDeocratorResolver.GetLayoutDecoratorFor(frameworkElement));
}

public void Register(ILayout layout)
{
	if (layouts.ContainsKey(layout.Name))
		throw new DuplicateLayoutException("Layout names must be unique. A layout named '" + 
layout.Name + "' already exists."); layouts.Add(layout.Name, layout); }

The problem that I have here is that it looks like I am trying to specify the mechanics of the code under test, and that is a big mistake. I really should not care how it is doing it. I should care about the results. Therefor, I decided to change the test to:

[Test]
public void When_resolving_using_framework_element_will_add_layout_decorator_for_that_element()
{
}

Now what I am testing is behavior, not mechanics.

Tests that validate the mechanics of the code are brittle, and end up as testing shackles.