5/14/2008 4:51:00 PM

On "Software Developers Never Change"

Nick B writes today about some of the traditional "I'm smarter than you OR your mama" developers face. Though I would agree with an overwhelming majority of the points he makes and with virtually all of his rather comical approach, I feel as though I have something to add.

Best part is that it's relatively simple and I can make my point in a fraction of the time it took Nick to make his (not saying he took too long, I'm just going to be more condensed as I'm ready to go home). 

It's simple - there should never be a qualitative discussion of code. It's that stinking simple. If I do it with prototype and you do it with jquery, who gives a rat's ass which framework is better, so long as both approaches resolve to the same end? The bottom line is this - there is no such thing as better code, as long as the code you wrote solves the problem it was meant to solve. Just because a better way comes along, the old way does not automatically become the bad way. Improvement does not denote previous failure. Improvement is indicative of progress. 

There will always arise a better mouse trap if you wait long enough.

Kick it! | del.icio.us | Comments (1) | Permalink

1/29/2008 3:24:00 PM

Zooming with the Mouse Wheel in WPF

Not exactly sure if one could refer to this as "real zooming" or whatever, but it's a nifty trick that I've been thinking about implementing for a few days and finally had the time to do so. With that said, let's get to it. The point of this post is to explain how to allow for users who would like to zoom in on (or increase the size of, to be specific) specific controls on a WPF window. The code to do this is surprisingly simple. In fact, I'd be interested to see any improvements on this method.

The XAML code for a sample window is below. Note that I've just added one simple Rectangle to the window's Grid and attached the MouseWheel event to my local OnMouseWheel event handler. I'll examine the code for the OnMouseWheel handler in a moment, but for now here's some really simple XAML.

    5       <Grid>

    6         <Rectangle MouseWheel="OnMouseWheel" Width="100" Height="100" Name="rectangle1">

    7             <Rectangle.Fill>

    8                 <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">

    9                     <GradientStop Color="ForestGreen" Offset=".1"/>

   10                     <GradientStop Color="Khaki" Offset=".6"/>

   11                 </LinearGradientBrush>

   12             </Rectangle.Fill>

   13         </Rectangle>

   14     </Grid>

Of course, here's the handler method. In it, I examine the sender parameter as a FrameworkElement, as that's the base class for the majority of the controls for which I'd like to provide zoomability. Sure, I made the word up. Quit being cynical and look at the code.

   27         private void OnMouseWheel(object sender, MouseWheelEventArgs e)

   28         {

   29             FrameworkElement source = sender as FrameworkElement;

   30             if (source == null) return;

   31             source.Width = rectangle1.Width + (e.Delta / 10);

   32             source.Height = rectangle1.Width + (e.Delta / 10);

   33         }

That's it. You can attach this event handler to the MouseWheel event of any control that inherits from FrameworkElement and provide zoomability for your users.

Happy coding! 

Kick it! | del.icio.us | Comments (1) | Permalink

1/18/2008 10:04:00 AM

Excellent Noob RhinoMocks Post

Buddy, the Beginnermediate developer (I love that tagline BTW) has written an excellent blog post on Rhino Mocks. For someone like myself who understands TDD, implements it at a "B-minus" level and who thinks that mocks could help but have no idea how to get started, this post is a must-read. I can't wait to download RM now and get started. Excellent work!

Kick it! | del.icio.us | Comments (0) | Permalink

1/13/2008 12:39:00 AM

Dependency Injection Example - Constructor Injection and Service Orientation

With all the talk on weblogs or technical conversations within my own organization about DI it's difficult to ignore it as little more than the latest "new black" pattern. I've given it some considerable thought and until quite recently didn't really comprehend the overall niftiness of the DI approach. As with anything else it took a moment of "a-HA" to really grasp the power of DI; I was developing a custom CruiseControl.Net build plugin and realized that the plugins are injected dynamically at construction time. If you debug  one of these plugins, you'll notice that the plugin constructors don't match a common parameter structure. The one commonality throughout all the plugins I was investigating as examples for my own education seemed to be in the parameter types - they were all interfaces, implementations of which were usually stored in the CCNet server application domain.

Services, basically. My interest in service orientation perked my interest in DI; the two concepts appeared mutually beneficial. So I opened the laptop and started coding away on my own implementation of a DI framework, with tests (since it's virtually impossible to talk about DI without talking about tests, too). This blog post consists of an investigation into my own implementation. It doesn't offer up DI as a "holier-than-thou" approach nor a dismissable coding trend. Rather, it is my first attempt to prove to myself that I am getting this DI stuff and to implement it in my own words. *cracks knuckles*

First Things First - Support Laziness

As with any framework, I anticipate that the easier it is to use the more chance I'll have of talking someone else into giving this a shot or a glance. So I knew that I wanted my approach to be very simple to use, quick to implement, and hopefully, make the approach of using DI more interesting. My first question to every pattern is "does it make my coding process easier and more flexible?" I know that:

  • I'm going to implement DI here, so my dependent classes will "just pop up" because the "stuff" they need to "live" will be provided to them by some service layer. 
  • So I know I will need to implement ServiceContainer in some fashion, and the services I put into it will implement interfaces, since the Service approach implies the use of interfaces to define contracts.

My discomfort with the ServiceContainer approach is that, someone actually has to "Add" the service implementations to the service container. Hence, they have to:

  • Know how to do that.
  • Do it the way you expect they're going to do it .
  • Write their code in such a way that they account for my service container implementation.

That point, most times, is where I get pretty aggravated when I'm using someone else's framework. That is a requirement that I must not impose on my audience, but one that I can't get started without. So a compromise is in order, and I'll use the idea of simple metadata to notify me of interfaces the developer intends need to be added to the service layer at run-time.

    1     /// <summary>

    2     /// Defines an interface as one that should be created and hosted by the

    3     /// service host during application run-time.

    4     /// </summary>

    5     [AttributeUsage(AttributeTargets.Interface, AllowMultiple=false)]

    6     public class DependencyServiceInterfaceAttribute : Attribute

    7     {

    8     }

Using the DSI attribute I can mark any interface that I intend to be added to a service container instance within the application domain. This makes it really easy to use, as the code below indicates. 

   76 [DependencyServiceInterface]

   77     public interface IMockServiceA

   78     {

   79         void DoMockServiceWork();

   80     }

   81 

   82     [DependencyServiceInterface]

   83     public interface IMockServiceB

   84     {

   85         void DoMoreWork();

   86     }

   87 

   88     public class MockServiceA : IMockServiceA

   89     {

   90         #region IMockService Members

   91 

   92         public void DoMockServiceWork()

   93         {

   94             System.Diagnostics.Debug.WriteLine("Doing Mock Service A's Job");

   95         }

   96 

   97         #endregion

   98     }

   99 

  100     public class MockServiceB : IMockServiceB

  101     {

  102         #region IMockServiceB Members

  103 

  104         public void DoMoreWork()

  105         {

  106             System.Diagnostics.Debug.WriteLine("Doing Mock Service B's Job");

  107         }

  108 

  109         #endregion

  110     }

I create a new interfaces and mark them with the DSI attribute. Then, I implement each interface with a custom class containing some basic functionality. Notice that I don't have to do anything to the classes themselves; the DI layer we'll begin to investigate next will do that work for us. 

Comprehensive - Sure, Why Not?!

If you can see where I'm going with this you're most likely scratching your head and saying "no way, not everything..." Looking through each assembly for implementations of interfaces marked with metadata isn't the most performant approach to doing type-loading but for now it will serve it's purpose. Think of it this way - I'm making exhaustively sure I'm not going to miss any service implementation that I might need later by a dependent class.  If I suspect that any interface I've got implementations of will ever be needed by any dependent class that might be required later, I can just slap the DSI attribute onto the interface and off we go.

Just to take a quick look at the code that'd perform this exhaustive search it's right here. The DependencyServiceContainer does just what you suspected - it looks through everything in the application domain to find any implementations of any interfaces that have been marked with the DSI attribute. Whenever it finds such an implementation, an instance of it is created and added via the base method ServiceContainer.AddService.

    8 public class DependencyServiceContainer : ServiceContainer

    9     {

   10         public static DependencyServiceContainer Instance

   11         {

   12             get { return _instance; }

   13         }

   14 

   15         static DependencyServiceContainer _instance;

   16         static DependencyServiceContainer()

   17         {

   18             _instance = new DependencyServiceContainer();

   19         }

   20 

   21         internal DependencyServiceContainer()

   22         {

   23             Preload();

   24         }

   25 

   26         private int _svcCount;

   27         public int ServiceCount

   28         {

   29             get { return _svcCount; }

   30         }

   31 

   32         void Preload()

   33         {

   34             foreach (Assembly assm in AppDomain.CurrentDomain.GetAssemblies())

   35             {

   36                 SearchAssemblyForDSIAttributes(assm);

   37             }

   38         }

   39 

   40         void SearchAssemblyForDSIAttributes(Assembly assm)

   41         {

   42             foreach (Type tp in assm.GetTypes())

   43             {

   44                 if (!tp.IsInterface)

   45                 {

   46                     SearchTypeForInterfaces(tp);

   47                 }

   48             }

   49         }

   50 

   51         void SearchTypeForInterfaces(Type t)

   52         {

   53             foreach (Type intrfc in t.GetInterfaces())

   54             {

   55                 if (IsInterfaceDSI(intrfc))

   56                 {

   57                     AddService(

   58                         intrfc,

   59                         Activator.CreateInstance(t)

   60                     );

   61 

   62                     _svcCount++;

   63                 }

   64             }

   65         }

   66 

   67         internal static bool IsInterfaceDependencyInjectable(Type intrfc)

   68         {

   69             return (

   70                 (intrfc.GetCustomAttributes(typeof(DependencyServiceInterfaceAttribute), false).Length > 0)

   71                 &&

   72                 (intrfc.IsInterface)

   73             );

   74         }

   75 

   76         bool IsInterfaceDSI(Type intrfc)

   77         {

   78             return DependencyServiceContainer.IsInterfaceDependencyInjectable(intrfc);

   79         }

   80     }

Activation of Dependent Objects - the Point

Now that the DI framework has a service container into which services required by dependent classes have been added the logic to create dependent objects must be created. Basically, we're going to use reflection to inspect dependent classes. During reflection each constructor signature will be observed. When a constructor is found that has parameters of interface types that are all being held within the DependencyServiceContainer, the constructor will be called and the resulting object returned. 

    8 public class DependentClassActivator

    9     {

   10         static DependentClassActivator _instance;

   11         static DependentClassActivator()

   12         {

   13             _instance = new DependentClassActivator();

   14         }

   15 

   16         public static DependentClassActivator Instance

   17         {

   18             get { return _instance; }

   19         }

   20 

   21         public T CreateInstance<T>() where T : class

   22         {

   23             Type tp = typeof(T);

   24 

   25             foreach (ConstructorInfo ctor in tp.GetConstructors())

   26             {

   27                 if (Observe(ctor))

   28                 {

   29                     return InvokeConstructor<T>(ctor);

   30                 }

   31             }

   32 

   33             return null;

   34         }

   35 

   36         #region Private Helper Methods

   37 

   38         bool Observe(ConstructorInfo ctor)

   39         {

   40             foreach (ParameterInfo prm in ctor.GetParameters())

   41             {

   42                 if (!Observe(prm)) return false;

   43             }

   44 

   45             return true;

   46         }

   47 

   48         bool Observe(ParameterInfo prm)

   49         {

   50             return (

   51                 DependencyServiceContainer.IsInterfaceDependencyInjectable(prm.ParameterType) &&

   52                 GetTypeFromServiceContainer(prm.ParameterType)

   53             );

   54         }

   55 

   56         bool GetTypeFromServiceContainer(Type intrfc)

   57         {

   58             return (DependencyServiceContainer.Instance.GetService(intrfc) != null);

   59         }

   60 

   61         T InvokeConstructor<T>(ConstructorInfo ctor) where T : class

   62         {

   63             object[] prms = GetConstructorParametersFromServiceContainer(ctor);

   64             return ctor.Invoke(prms) as T;

   65         }

   66 

   67         object[] GetConstructorParametersFromServiceContainer(ConstructorInfo ctor)

   68         {

   69             List<object> prms = new List<object>();

   70 

   71             foreach (ParameterInfo prm in ctor.GetParameters())

   72             {

   73                 prms.Add(DependencyServiceContainer.Instance.GetService(prm.ParameterType));

   74             }

   75 

   76             return prms.ToArray();

   77         }

   78 

   79         #endregion

   80     }

Here's the basic run-down. The DependentClassActivator creates looks at all of a class's constructors. Specifically, at each constructor's parameter. When it finds a constructor that has parameters it sees in the DependencyServiceContainer, it calls that constructor. So you don't have to use your class's constructors any longer. Instead, you tell the new DependentClassActivator to give you an instance, instead. Something like this:

   27             MockServiceA a = DependentClassActivator.Instance.CreateInstance<MockServiceA>();

 

To use a metaphor, it's like walking into a kitchen in which everything you ever need to make anything is already there. You need a spatula, you got it, you need a mixer, you got it. And so on.

How Do You Test It?

Possibly the most important aspect of all this is the ability to test it. In fact, code written using this DI framework is rather simplistic to test. To explain how you'd use this approach we'll consider the ever-relevant banking scenario. Below you'll see the test code for all the functionality described earlier. You'll see some interfaces that have been marked with the DSI attribute, some implementations to create and use, and tie it all up with a mock banking execution example.

 

   10 #region Bank Service Interfaces and Implementations

   11 

   12     public class Account

   13     {

   14         private int _accountId;

   15         private decimal _bal;

   16 

   17         public decimal Balance

   18         {

   19             get { return _bal; }

   20             set { _bal = value; }

   21         }

   22 

   23         public int AccountId

   24         {

   25             get { return _accountId; }

   26             set { _accountId = value; }

   27         }

   28     }

   29 

   30     [DependencyServiceInterface]

   31     public interface IAccountLookupService

   32     {

   33         Account FindAccount(int accountId);

   34     }

   35 

   36     [DependencyServiceInterface]

   37     public interface IWithdrawalService

   38     {

   39         bool Withdraw(Account account, decimal amount);

   40     }

   41 

   42     [DependencyServiceInterface]

   43     public interface IDepositService

   44     {

   45         bool Deposit(Account account, decimal amount);

   46     }

   47 

   48     public class AccountLookup : IAccountLookupService

   49     {

   50         #region IAccountLookupService Members

   51 

   52         public Account FindAccount(int accountId)

   53         {

   54             if (accountId != 1234) return null;

   55 

   56             Account mockAccount = new Account();

   57             mockAccount.AccountId = 1234;

   58             mockAccount.Balance = 100;

   59             return mockAccount;

   60         }

   61 

   62         #endregion

   63     }

   64 

   65     public class AccountWithdrawer : IWithdrawalService

   66     {

   67         #region IWithdrawalService Members

   68 

   69         public bool Withdraw(Account account, decimal amount)

   70         {

   71             if (amount > account.Balance) return false;

   72             account.Balance -= amount;

   73             return true;

   74         }

   75 

   76         #endregion

   77     }

   78 

   79     public class AccountDepositer : IDepositService

   80     {

   81         #region IDepositService Members

   82 

   83         public bool Deposit(Account account, decimal amount)

   84         {

   85             account.Balance += amount;

   86             return true;

   87         }

   88 

   89         #endregion

   90     }

   91 

   92     public class Bank

   93     {

   94         IAccountLookupService lookupService;

   95         IWithdrawalService withdrawalService;

   96         IDepositService depositService;

   97 

   98         public Bank(IAccountLookupService lookupService,

   99             IWithdrawalService withdrawalService,

  100             IDepositService depositService)

  101         {

  102             this.lookupService = lookupService;

  103             this.withdrawalService = withdrawalService;

  104             this.depositService = depositService;

  105         }

  106 

  107         public Account GetAccount(int id)

  108         {

  109             return this.lookupService.FindAccount(id);

  110         }

  111 

  112         public bool Withdraw(Account account, decimal amount)

  113         {

  114             return this.withdrawalService.Withdraw(account, amount);

  115         }

  116 

  117         public bool Deposit(Account account, decimal amount)

  118         {

  119             return this.depositService.Deposit(account, amount);

  120         }

  121     }

  122 

  123     #endregion

  124 

  125     #region Tests

  126 

  127     [TestFixture]

  128     public class BankAccountTests

  129     {

  130         [SetUp]

  131         public void Setup()

  132         {

  133         }

  134 

  135         [TearDown]

  136         public void TearDown()

  137         {

  138         }

  139 

  140         [Test]

  141         public void CanBankClassBeCreated()

  142         {

  143             Bank bank = DependentClassActivator.Instance.CreateInstance<Bank>();

  144             Assert.IsNotNull(bank);

  145         }

  146 

  147         [Test]

  148         public void CanBankHandBackAccount()

  149         {

  150             Bank bank = DependentClassActivator.Instance.CreateInstance<Bank>();

  151             Account account  = bank.GetAccount(1234);

  152             Assert.IsNotNull(account );

  153             account = bank.GetAccount(1000);

  154             Assert.IsNull(account );

  155         }

  156 

  157         [Test]

  158         public void CanBankAccountWithdrawMoney()

  159         {

  160             Bank bank = DependentClassActivator.Instance.CreateInstance<Bank>();

  161             Account account = bank.GetAccount(1234);

  162             Assert.IsNotNull(account);

  163             decimal bal = account.Balance;

  164             decimal amt = 42;

  165 

  166             bool result = bank.Withdraw(account , amt);

  167             Assert.IsTrue(result);

  168             Assert.AreEqual((bal - amt), account .Balance);

  169 

  170             result = bank.Withdraw(account , 99999999);

  171             Assert.IsFalse(result);

  172         }

  173 

  174         [Test]

  175         public void CanBankAccountDepositMoney()

  176         {

  177             Bank bank = DependentClassActivator.Instance.CreateInstance<Bank>();

  178             Account account = bank.GetAccount(1234);

  179             Assert.IsNotNull(account );

  180             decimal bal = account .Balance;

  181             decimal amt = 42;

  182 

  183             bool result = bank.Deposit(account , amt);

  184             Assert.IsTrue(result);

  185             Assert.AreEqual((bal + amt), account .Balance);

  186         }

  187     }

  188 

  189     #endregion

I welcome any comments on this approach. Is this DI or have I completely missed the boat on this whole concept. Hopefully this look at one appraoch DI has been as enlightening as it has been for me. Happy coding!

Kick it! | del.icio.us | Comments (1) | Permalink

12/19/2007 12:09:00 PM

Using a ServiceContainer with Delegates - Truly Simple Services

While working with a colleague on a project I got into a debate about event-handling versus delegates stuffed into a service container. It sounded weird to me at the time; I've always been a huge fan of event-driven programming so I tend to lean that way when I need to make my objects responsive to one another. The way my colleague looks at it, "everything's a service, so if you just add your methods that you need to run to your service container you can call them when you need them." The idea seemed truly nutty to me so I just had to code it up. It is important to note here that our system already made use of the ServiceContainer approach. We have a custom service container that our applications use; in this way we can add any service to the container at run-time and provide our whole application (and all of it's components) with access to everything via the service container. If you're not familliar with that approach this may seem a little off-kilter. 

First thing I did was to create a custom ServiceContainer implementation. The code for my GenericServiceContainer is below. Note the extra method I've added which makes use of generic types. 

    7     public class GenericServiceContainer : System.ComponentModel.Design.ServiceContainer

    8     {

    9         public virtual T GetService<T>() where T : class

   10         {

   11             return this.GetService(typeof(T)) as T;

   12         }

   13     }

Next, I'll create a few delegate types. In this way, any class that has knowledge of these delegate types can request the GSC send'em out. 

   11     public delegate void MessageDelegate(string message);

   12 

   13     public delegate int AdditionDelegate(int x, int y);

Though the functionality abstracted in the form of delegates I still need to create a class that can "do the work" for the application. To accomplish this I've written a simple WorkerClass, the code for which is below. 

   15     public class WorkerClass

   16     {

   17         public static void ShowMessage(string message)

   18         {

   19             Console.WriteLine(message);

   20         }

   21 

   22         public static int Add(int x, int y)

   23         {

   24             return (x + y);

   25         }

   26     }

Finally, some tests will prove the theory.  

   28     [TestFixture]

   29     public class TestServiceContainer

   30     {

   31         GenericServiceContainer _container;

   32 

   33         [SetUp]

   34         public void Setup()

   35         {

   36             _container = new GenericServiceContainer();

   37 

   38             _container.AddService(typeof(MessageDelegate),

   39                 new MessageDelegate(WorkerClass.ShowMessage));

   40             _container.AddService(typeof(AdditionDelegate),

   41                 new AdditionDelegate(WorkerClass.Add));

   42         }

   43 

   44         [TearDown]

   45         public void TearDown()

   46         {

   47             _container.Dispose();

   48         }

   49 

   50         [Test]

   51         public void TestMessageDelegate()

   52         {

   53             MessageDelegate del = _container.GetService<MessageDelegate>();

   54             Assert.IsNotNull(del);

   55 

   56             del.Invoke("Testing");

   57         }

   58 

   59         [Test]

   60         public void TestAdditionDelegate()

   61         {

   62             AdditionDelegate del = _container.GetService<AdditionDelegate>();

   63             Assert.IsNotNull(del);

   64 

   65             int result = del.Invoke(2, 2);

   66             Assert.AreEqual(result, (2 + 2));

   67         }

   68     }

So that's it! With this code I've defined the structure of the methods that will be doing the work and allowed redirection to a worker class to perform the work. Now, any class within the application being augmented by my custom ServiceContainer can have easy access to centralized functionality.

Happy Coding! 

Kick it! | del.icio.us | Comments (1) | Permalink