Wednesday, January 24, 2007

Custom Actions

So I just finished adding in the final main feature of the E# language. I've been kicking around a few other ideas but have discarded them (at least for now) and I'm pretty sure that this is it. Actually, I still have to add the ability to declare an "expression" but that should be pretty simple compared to everything else.

So the new feature I'm talking about of course is the "action" declaration feature. This brings me one step closer to the philosophy that Rocky Lhotka has been talking about, which is that business objects should be defined by behavior and not data. In this case, as you're designing your entities you can specify the behavior in a lot of ways and one of them is by declaring an action. Here is an example:
family Business
entity Example
action DoWork when changed;

In the above example we declare the action "DoWork" and specify it to be executed when the entity has been changed. There are about 20 reserved event keywords (such as deleting, deleted, fetching, fetched, persisting, validating, accessed, etc.) that you can attach your actions to. Also you can choose to not attach them to anything at all by leaving off the when clause entirely. So here are some other examples of declaring actions:

action Log on Business.Custom.Utilities when changed;
action ProcessMessage when persisted async;

The "on ..." syntax specifies the object in which the expected method of this action is to be found. This requires the actions method to be static, whereas not specifying an "on" clause requires the method to be part of "this", which means it must be defined in a partial class. Also the "async" specifier will execute that event asynchronously rather than the standard synchronous execution. The "async" keyword only applies to actions with a when clause.

So you might ask yourself why you would want to specify actions? Well it's pretty nice really, the whole point is that when you are wearing the architect hat you want to think about your problem not so much as just what types of data you need to pass around but as what types of behavior you want fulfilled. In this case as you are architecting your entities you would be able to specify which actions are exepcted of it, beyond the behaviors implied by persistence, validation etc. The methods that these actions attach to are not generated by the E# compiler but instead they must be manually created. If they do not exist the compiler will complain and tell you that a method is missing. So as the architect you can specify the actions that the developers then have to go and implement them.

Next you might ask, well what is going on under the hood? It turns out to be pretty simple really. The hardest part is just getting all the dang events coded and executing at the right times in the EntityBase class but what ends up happening from the templates perspective is that a method is implemented called Load_Actions and in there event handlers are added to the various events pointing to the specified methods which gets called at construction time. So if the method is not implemented the C# compiler will complain about it. The only trick is for actions that have no when clause specified. For this case I have added a protected event called Never, which the methods get attached to. The Never event never gets called (as you can imagine) but it will get the C# compiler to complain about missing methods! So that's my little hack of the day.


Post a Comment

Links to this post:

Create a Link

<< Home