Thursday, May 29, 2008

Code Complete LOLCat

I was out on the porch reading 'Code Complete' by Steve Mcconnell the other night and when I came back outside from getting something to eat, I found this:

"im in ur books farting on yer c0dez..."

Sunday, May 18, 2008

Workflow Foundation Rules Engine

I've been working a bit lately with the Workflow Foundation Rules Engine. It's just too cool not to blog something about it.

The whole idea behind the rules engine and where it's value lies is that you can update and create rules on the fly outside of your compiled assemblies. All of your rules (if/and/or/else logic) get serialized to an ASCII XML file that can be stored anywhere. This is great for rapidly changing business environments where instead of calling IT and doing a development cycle, a business guy can fire up an editor and start changing the way the application works.

Get Started

The API for the Rules Engine is included with the .NET framework 3.0, but can be used totally independently of Workflow.
I recommend these two articles to get some good samples running to where you can run through and debug and get some sense of what's happening:

http://richardsbraindump.blogspot.com/2007/08/how-to-use-windows-workflow-rules.html
http://odetocode.com/Blogs/scott/archive/2006/10/01/7293.aspx

And this demo is a good one to grab (from the netfx3 site):
http://wf.netfx3.com/files/folders/rules_samples/entry309.aspx

How to update the rules

The link above to the demo at netfx3.com has included with it a kind of "crude" rule editor. I found it pretty painless to use, but I'm not so sure about a business guy with no dev experience. The cool thing about the engine is that it is completely open. Here is one 3rd party tool available(that I could find easily) InRule.

Speed

If you go out on the net and Google for this topic you're going to find tons of insanely in depth articles about WF rules vs. Biztalk BRE (Business Rules Engine). In the end the winner is the BRE, but the only way you're going to notice more than a trivial performance difference is if you're running millions and millions of requests simultaneously. For most situations WF rules are going to give you sufficient performance.

Technique

The only real challenge for me in getting started was figuring out what the best technique was for using the rules engine. Here's my take...
Essentially you are passing the rules engine a simple .NET object. Any decisions that you want the rule engine to make have to be stored within that object. What I found it easiest to do is create methods that make it easy for the user to add results that will be easy to read by the application after the engine has been ran.

So here's the way I've found easiest to design and implement the rules engine.

1) Create a simple .NET class that will hold all of your "facts". These facts are the data that will allow you (or your business user) to evaluate from the rules engine (via a GUI rules editor). I imagine using a translation class to take your true business objects and pull certain properties and collections over to a newly instantiated class to pass to the engine.

2) Think of how your business user is going to use the rule editor. Any method that you write in the class being passed to the rule engine can be called from the rules designer. You can use these methods to add shortcuts or allow the user to perform more complex operations as the rules execute.

The rule editor (found in the demo link above)
DemoRuleEditor

3) Add attributes to the rule sets that allow you to filter which rule sets apply to the problem you are trying to solve. These attributes will be used to filter only applicable rule sets when you go to run the rules engine. This is also where you can 'version' your rulesets. Use these version columns to keep a history of the way the rulesets have changed over time. ("RuleSet" here is a custom object that I am using to store the rule-xml and data about the rule set.)

When you have your collection of RuleSet objects, loop through and allow the rules engine to evaluate them:

The 'c' object below is the custom object that I am using to hold all the facts to send to the rule engine.

List<BusinessRuleRecord> ruleSets = dbm.getBusinessRuleRecordsWhere("Insert SQL Query Here -- AND VersionMajor = 1 AND VersionMinor = 0");

RuleSetService svc = new RuleSetService();

foreach (RuleData.BusinessRuleRecord rule in ruleSets)

{

RuleSet ruleset = svc.GetRuleSet(new RuleSetInfo(rule.Name)); //RuleSet = System.Workflow.Activities.Rules object.

RuleExecution exec = new RuleExecution(new RuleValidation(c.GetType(), null), c);

ruleset.Execute(exec);

}


So what this did is went out to my database and grabbed all the rulesets that applied to my data and executed them. Pretty simple implementation - but I think the key to keeping the performance up is only selectively running your rules.

I think that Workflow and the rules engine is some of the neatest technology that's been released lately. I hope to be spending a lot more time in these namespaces in the next few months trying to learn when it would be appropriate to use this technology in real world scenarios.

Launchy Won't ....Launch?

My favorite keystroke launcher, launchy appeared to stop working today.  I used my favorite keyboard combo (ALT+SPACE), and the familiar launchy suggestion box would not show.

The funny thing was that Launchy was running.  I saw launchy.exe in the process explorer in task manager.  My theory was that launchy was displaying, but off the bounds of my screen.  A trip into C:\Users\Steve\AppData\Roaming\Launchy revealed the problem.  (You may need to allow windows explorer to show all hidden files and folders).  I opened launchy.ini and explored it's contents. 

Capture

Those coordinates clearly put the launchy window outside the bounds of my screen.  I changed the coords to something a little more reasonable [pos=@Point(20 20)].  I killed the process and re-launched the app.  Everything is now back to working order.

Saturday, May 17, 2008

A Lesson About GFCIs

I learned a lesson in residential electric today when I went to hook up and turn on a fan in my garage. The fan wouldn't turn on. Checked another electrical device in the outlet and quickly determined there was something wrong with the outlet. So I ran an extension cord from the basement from another outlet to provide an alternate source of power to the fan - still no luck, this outlet was dead too...but the real bummer about that outlet is it was powering my freezer ...by the looks/smell of the food my outlets had probably been out for 12-24 hours. CRAP! What gives?

So I turned to the fuse box, nothing tripped. Then I call my electrician (dad) and after hearing the problem he decides he needs to do a housecall. We tested all the circuit breakers to all areas of the house and determined that I did not have any bad breakers. Then, after almost giving up and resolving to the fact of having to shell out a few hundo to an electrician - inspiration struck. Had a GFCI been tripped? (GFCI's protect you from shock by sensing ground faults (you being shocked) and shutting off juice to the outlet if it senses any change in current caused by a ground fault.) The thought had never occurred to either of us at first because both of the switches that were out did not have the common GFCI 'test' and 'reset' switches as seen below:

gfci_outlet

We went around the house to all of the outlets with the GFCI switches on them and made sure that they did not need reset. Well - one of them did need reset; my wife's bathroom had an outlet that had been tripped. So why did it have any effect on the outlet in my garage and basement? It turns out that for any given line from a circuit in your breaker box you can monitor for ground faults on all outlets on that line by installing only one GFCI outlet on the line. So in my case all I needed to do was hit the reset button and both of my affected outlets were hot again. Thanks Dad!

Tuesday, May 13, 2008

Subversion And Tortoise: Filter Unwanted Files/Folders From Being Checked Into Your Repository

As part of my ritual of adding a directory/project to my source control repository at home using Subversion and Tortoise, I always go into the repository and remove all of the files that I do not want to be source controlled. These are files such as *.PDB, *.EXE, etc. I don't want these to be under source control because Tortoise will see a change to these files when I build the application - even if I haven't actually touched source code. This causes the red exclamation indicator to turn on for my project folder - which sends my OCD reflex through the roof.

So I found a simple answer to this problem tonight. You can configure Tortoise to not check in files and/or folders with extensions that you specify.

First, right click on any folder in windows explorer that is under source control. In the context menu go to TortoiseSVN -> Settings.

You should see:

Settings

Now when you check import a new project, the files with the extensions in the 'Global ignore pattern' box will not be uploaded. Cool!

7/23/08 Update:
Here is the string I'm using currently to filter out unwanted files:
bin obj *.user Debug Release *.aps *.eto [Bb]in [Dd]ebug [Rr]elease _ReSharper.* *.cache CommonAssemblyInfo.cs *.suo *.user *.resharper

Saturday, May 10, 2008

Cloning Objects In .Net

(Download source at the end of the article)

The issue of cloning pops up about once a year for me, and I'm always perplexed at the complexity of what seems to be a very simple thing...give me a copy of my object, please!

This is what you want to do, but of course it won't work:

Foo f = new Foo();

Foo f2 = new Foo();

f = f2; //'Point' variable f to the memory where variable f2 resides


This is what is referred to as 'shallow cloning'. Essentially with the above code, you have two variables pointing to the same space in memory. In all the research I've done, there seems to be confusion about what is a 'deep clone'. If I am told that a method will do a deep clone, I am assuming that the object, all it's properties, and all their children's properties will be cloned along with it. (I'm going to call this 'recursive cloning'.) However, in a lot of my reading not everyone holds this to be true. Many people will tell you that deep cloning is only cloning properties one level deep...as such:

    [Serializable]
    public class A : BaseClass
    {
        public string AProp { get; set; } //Cloned
        public List<B> AChildren { get; set; } //Copies a reference from the source object
    }
 
    [Serializable]
    public class B : BaseClass
    {
        public string BProp { get; set; } //Not cloned
        public List<C> BChildren { get; set; } //Not cloned
    }

So now that I have that straight in my mind, I need to think about my options.

1) Manual clone
For each one of your objects, implement the ICloneable interface and new up your object and start assigning your object's properties to the new object. (Sidebar: It's becoming taboo to use ICloneable.)

I'm throwing out a manual cloning technique, because I'm lazy and who wants to have to remember to add another line of code in your Clone() method every time you add a property. You can get your recursive clone using this approach, but it's going to be time consuming and make your code less readable. My vision for a clone method is to sock it away in a base class...with manual cloning you're going to have to implement a Clone() method for each concrete class.

2) Reflection
Code using reflection is hard to read - I'll say that first because it's my biggest peeve with it. Besides that, you're going to have a hard time implementing a 'recursive clone' with it. The reason its difficult is because you have to implement a clone implementation for each generic collection type. If you're only using primitives (string, int, long, etc) then it's great.
3) Serialization
This is the clear winner. Serializing your object to another place in memory and then de-serializing it into a new instance is a great way to get a recursive clone. If you don't want to clone a particular field, just use the [NonSerialized] attribute.
I did a quick and dirty performance test on a clone method using reflection(doing a recursive clone) and a method using serialization. Here are the results:

For 100,000 objects with an object graph 3 levels deep (see sample app attached):
Serialization: 20.234 seconds.
Reflection: 17.613 seconds.

Download the source here for an example of cloning using serialization and reflection.

Why is cloning useful?
Two reasons I can think of off the top of my head:

1) To allow your user to create a copy of a domain object in the application. Maybe you want to allow the user to copy an "Order" object because they want to create a new order object with very similar details to an existing one, but don't want to go through all the work to create it by scratch.

2) To keep track of state changes to your object. This is especially applicable when developing SOAs. The client made changes to your object, but before you apply the changes you want to keep a copy in memory so you can say things like "if the user changed the status, then we need to do xyz."

Monday, May 05, 2008

Network Attached Storage (NAS) Options

hard-drive-flames

With the birth of our first child, we are taking absurd amounts of photos and videos. This all adds up to many gigabytes of needed storage, and my backup strategy for those files up to this point has been somewhat of a pain. What I need is a high volume storage solution, and I know that I want something that will support RAID mirroring. So I started to look at my options. After looking around for a bit I realized that with all my options, I really needed to take notes and determine pros and cons to each.

Here is a link to my notes. I'm leaning heavily to the build-your-own solution. It's mainly for the geek coolness factor - but really it comes down to the flexibility it provides.