Technology with opinion
Monday, April 26, 2010
NDepend 3.0 analysis of NAsserter
I recently posted some code to Google Code called NAsserter. NAsserter started off as a proof of concept for prototyping something I had been able to do within Unit Tests (being able to make fluent style assertions in code) except for the purpose of throwing exceptions in code. This is the first fluent API I have written.
The API for NAsserter started as a small simple class and grew bit by bit. I tried to refactor as much as it made sense to me. I didn't model my internal constructs after any other fluent library as most of them have a need for much more extensibility than this. The biggest inspirations were NUnitEx, NUnit's constraint based model and Fluent Validation. These three projects provide exactly what they aim to, in which NAsserter is not intended to overlap. NAsserter is NOT a Unit Testing or Validation framework. It's simply for throwing exceptions in a predictable manner, including the messages. Thanks to Tuna (NHibernate & Castle contributor) constructive feedback.
Upon getting a version of NAsserter (0.1) released that I am comfortable with, I proceeded to analyze it with NDepend; which I am still learning.
One of my favorite sections of the report is the assembly metrics which shows how abstract, stable, complex and well commented the code is. I think the metrics of what you are looking for may be a little different based on if you are developing a framework (even the type of framework) or enterprise systems. For instance, often times frameworks developers will make compromises in design for simplicity of use which is pragmatic: use common sense.
NAsserter is a simple codebase which shows through the analysis (the only dependency is mscorlib the .Net CLR) and doesn't really do NDepend justice. NDepend is nice on large projects with a number of dependencies, especially for keeping track of different design metrics. I am still learning the tool myself and I am finding new uses for it continually. You can track your project's progress on different metrics since it keeps a baseline of the metrics. NDepend is also very helpful for code reviews to be able to have an objective analysis of code, reducing some of the human element.
Thursday, April 15, 2010
Generic Singleton Factory
Not too long after writing and blogging about a generic singleton base, I changed the code to use a Factory - a singleton factory to be specific. Below is a factory which can be used to create a singleton instance of any class. The original singleton base class implementors needed to be sealed or have unintended consequences of getting an instance of the wrong class. This caused me to reflect and conclude that the design was deceptive as it was almost in essense a factory.
Below is a refactored version which is a little more genuine. This is my first crack, and requires generics. I do not use this everywhere I use singletons but where the usage of a Factory fits better than a singleton such as when you have many implementors of the same interface and you want singleton creational behavior.
Jon Skeet's has a great article on some different singleton designs in his blog.
Wednesday, April 07, 2010
Automatically mapping objects of same derived types
I had a need to automatically map all properties from one class to another class. These two classes had the same derived type, this was by design and not by accident. FYI: this example's Unit Test uses NUnit (2.5), NBuilder, both are optional as the test below can be easily adapted.
The scenario goes like this: you have a base class called BaseTransaction with derived classes DebitTransaction and CreditTransaction. Often where there are many properties from the base class to map, it's redundant to write and tedious. This bit of reflection below iterates through each property of the base class and maps it to a new object that it creates and returns this object.
The following unit test shows the usage of this function, as well as outputs to the console showing that the bases members were in fact mapped. Each derived class has unique properties of the same name (TransactionId), neither of these were mapped - otherwise an exception would have been thrown during the reflection code (prop.SetValue...).
Thursday, April 01, 2010
DRY is dead, long live MOISTURE
DRY has become a big buzzword these days that puts emphasis on reusability. While there are some advantages to reuse, I'm going to look at the downside; having DRY applications which are rigid crack over time due to the lack of Moisture.
What is Moisture? It is the syntactic sugar that makes procedural languages like JScript, VBScript, FoxPro and T-SQL powerful and fast. Unless you've been hiding in a cave, you have started migrating from an ORM (such as NHibernate) to more future-proof constructs like Stored Procedures or DataSets.
In the past, the only downside to Stored Procedures was that Refactoring them took a lot of effort. However, JetBrains has recently announced ReProcedural to which lets you refactor code written in VBScript, Microsoft JScript or T-SQL
Once you have moved all of your business logic to stored procedures, just plan on having an average of 4 stored procedures per table (for insert, update, delete and select). In a medium sized system with 50 tables, it's completely acceptable to have an upwards of 200 stored procedures or more. At this point, your team should have enough T-SQL work to justify having a DBA letting you focus on increasing system Moisture with procedural programming
Finally, you will want to rewrite any aspects (AOP) as table triggers. For non-DBAs out there, triggers are essentially AOP for databases. For instance, if you wanted to implement logging your pointcut will either be your Stored Procedure or your Trigger.
Remember the basics of Moisture: the more OO code you can migrate to a procedural language, the better. While you can do procedural programming in C# or Java, it's not something enforceable as there is nothing stopping some n00b developer from creating an Interface or an Abstract Class. As a general rule, all methods should be public and static
April Fools!!! :-)