Enforcing IoC by Preventing Manual Instantiation

By Ryan at July 30, 2010 17:54
Filed Under: Development

Inversion of Control (IoC) has become a mainstay of programming in strongly-typed languages.  While IoC is an extremely powerful pattern, I've found it hard to enforce its usage in a team where not all members of the team are used to working with it.

 

Ideally, I don't want to see an 'new' statements in my application.  All instances should be provided by the IoC container, or, at very least, a service locator.  So how do you enforce this policy at compile time?  Well, one way is to mark the constructor as Obsolete.

 

Now, if you have Resharper installed, you'll know right away that there's a problem.  You may want to have a more informative message (this is just an example). Notice the second argument in the Obsolete attribute is set to true - this instructs the compiler to throw an error rather than a warning.  I find warnings are too easily ignored, but YMMV.

 

 

Regardless, now when you build, you will get a build error instantly notifying you of the problem

 

 

So there you have it, a simple, but effective way to enforce IoC and service location.

 

 

Execute application on battery event

By Ryan at March 17, 2010 16:59
Filed Under: Development

I was surprised to find out that there are no applications, apparently, that will allow you to execute an application, or perform some task, when transitioning from AC to DC (battery).  You see, I want to kill off extraneous processes when I switch to battery in order to conserve power.  When I'm back on AC, I want to restart them (potentially).

 

Now, there are ways to script this, but I need a low-profile, always-on, app running in the background waiting for a power broadcast (PowerModeChangedEvent).  Since I don't want to introduce more CPU overhead through a script, I opted to write a quick application to do what I wanted.

 

It's a really simple polling application that will execute actions based on an XML configuration file.  It can be easily extended to do other things; I just needed to knock this out real quick.

 

This project is now hosted on CodePlex.  You can get BatterySaver from here.

 

Brainstorming: Events

By Ryan at January 20, 2010 17:28
Filed Under: Development

While working on my side project, I’ve spent a lot of time trying to work out the best design. Keep in mind that this is more of a hobby for me, so I’m not trying to rush to publish a prototype to get VC.

I’ve worked in the enterprise application development space for several years, so I’m plenty familiar with separations of concerns. I realized, however, that there’s no good solution for handling the ancillary, “can the current user do X” and “if the current user does X, then do Y”. I’ve addressed this issue a number of ways in the past, none of which was particularly elegant. For instance, I’ve used AOP for cross-cutting concerns, but I found it too hard to test and not quite explicit enough.

So, I realized that these “meta-domain” concerns really aren’t concerns for the domain objects themselves. For instance, the User entity doesn’t care if a link is displayed on the user profile page based on security. In this case we could have a security manager that deals with this, but what if this decision isn’t just based on security, but also user reputation, user history and user profile settings? Do I suddenly need to couple my view-model to all of these managers/services? Do I have to have all of these redundant dependencies for every page? What if I forget one? How do I easily test what will happen?

These are all questions that I felt lacked a good answer. As a response, I created a library that is capable of registering “events” and “event” handlers. These aren’t traditional events, but more like “domain events” in that their scope is the entire domain.

Now, sure, there are other ways of accomplishing this, but my particular set of requirements calls for multiple actions to take place when certain events are fired. I also need to know if I can execute a given event, which makes them more than just fire-and-forget.

I had several requirements for my design: it had to be easy to use and understand, it had to play well with an IoC container, it had to be testable and it had to be as type-safe as possible. What I came up with seems to have accomplished all of these, though I haven’t put it to use just yet.

Here’s a snippet from one of the tests that illustrates one of the use cases. The AddNew method is defined on the IMockEventHandler interface. This returns a ValidationResult indicating whether or not the AddNew event can be called in the given MockContext based on all IMockEventHandler objects.

   1:  var result = eventManager.For<IMockEventHandler>()
   2:                           .In( new MockContext() )
   3:                           .Where( x => x.GetType().FullName.Contains( "Mock" ) )
   4:                           .Where( x => x.EventSourceType == null )
   5:                           .Validate( x => x.AddNew( "s" ) );

Typically the Where criteria won’t exist, they’re just there for flexibility.

So from the code snippet you can see some of the opportunities it presents. Say I have the following:
   1:  public interface IOrder {
   2:      void ShipOrder( string orderNumber );
   3:  }

   1:  public interface IOrderEventHandler {
   2:      HandlerResult ShipOrder( string orderNumber );
   3:  }

I expect to call something like this:
   1:  var result = eventManager.For<IOrderEventHandler>()
   2:                           .In( currentContext )
   3:                           .TryExecute( x => x.ShipOrder( orderNumber ), exec => { 
   4:                              currentOrder.ShipOrder( orderNumber );
   5:                            });

This will execute the given code if, and only if, the HandlerResult of the ShipOrder event handler returns HandlerResult.Success. The variable, result, will hold the HandlerResult so I can take action based on the result (throw an exception, rollback a transaction, etc.)

Now, from the UI perspective, we can have a special UI event handler:
   1:  public interface IOrderUIEventHandler {
   2:      HandlerResult DisplayDelete();
   3:  }

In the backing model, I can lazy load the permissions:
   1:  public CanDisplayDelete { 
   2:     get {
   3:        if( _displayDelete == null ) {
   4:           _displayDelete = false;
   5:           var result = eventManager.For<IOrderUIEventHandler>()
   6:                                    .In( currentContext )
   7:                                    .Validate( x => x.DisplayDelete() );
   8:           
   9:           if( result == HandlerResult.Success ) {
  10:              _displayDelete = true;
  11:           }
  12:        }
  13:        return _displayDelete;
  14:     }
  15:  }

The key, of course, is for the event manager to be extremely fast. I have tuned the hell out of it from a library persepective, but until I get it in a real application, I don’t have much to go on, but I expect the performance to be negligible. The only area where I need to be cautious is in the design of the event handlers themselves.

I also expect to fine-tune the syntax as it's a little "wordy" for me. I expect that I should be able to optimize the syntax down to a single-line evaluation:
   1:  eventManager.Validate( x => x.DisplayDelete() );

As I said, once I start using it, I'll be more apt to tune it.

EDIT: To be clear, this design is meant to address a particular problem: there may be a lot of entities interested in particular events and the decisions made may require input from multiple sources. This is not meant to delegate all functionality or business logic to event handlers.

Mixing solid design with code generation

By Ryan at October 09, 2009 08:47
Filed Under: Development

One thing about a good software design is there usually exist a number of layers of abstraction.  The problem is that this can start to become cumbersome to manage.  It's important, however, to recognize that there are tools out there to mitigate this and thus your design shouldn't suffer as an attempt to "simplify."

Simplification comes through abstraction and encapsulation.  If you find your architectural framework complex, you're probably not encapsulating the details enough.  I always design with a junior programmer in mind.  That is, could a junior-level programmer pick up my code and be productive in a short period of time.  If the answer is yes, then the design is "easy" to work with, though it may be "complex" under the covers.

The first way to simplify any design and the inherent testing thereof, is to use an Inversion of Control (IoC) framework.  There are many on the market (Spring, Unity, Castle Windsor, etc.)  Such frameworks allow for clear separation of concerns without hard-coding dependencies.  The real benefit is realized when unit testing.  Without an IoC framework, you'd (hopefully) do dependency injection manually, however this would require lots of plumbing to test a single component and lots of manual work.  IoC containers make this easier by "automatically" managing the dependency instantiation.  I great tongue-in-cheek overview can be found here.

Given all of that, I sometime still struggle with the perceived complexity of my code.  Most if the complexity (with respect to dependencies and separation of concerns) happens in the lower layers, from the service layer down.  Fortunately, most of this has a one-to-one mapping to a database.

Let me preface the following by saying that this only applies to websites, as opposed to shippable products.

Now, call me old-fashioned, but I don't like ORMs.  Well, more specifically, I don't like ORMs when there's little chance of a change to the underlying datastore provider.  I don't feel like I get the level of control that I want, and, given my experience perf-tuning applications for production, I feel that I'm justified.  I say this because the ORMs abstract away the database interaction and, following my "junior developer" thought process makes it easy for developers to write horrible data access code.  I feel it's of much more value for a junior developer to become familiar with a particular database vendor (SQL Server in the .NET world, for instance) than an ORM that may or may not be used at the next job they get.  If you understand how the underlying system works, you can then work at a higher level with getter effectiveness.

So, in order to achieve the same effect of an ORM, I simply use code generation.  This is far simpler in .NET than in Java to due to certain language constructs.  By generating the code, I don't waste CPU cycles at runtime as various mappings and pseudo-SQL expression are worked out.  I simply send the query to the db provider.  Sure, this SQL could be vendor-specific, but I find that 90% of the time, I can write ANSI SQL query that SQL Server, Oracle, MySql, DB2, etc could process.  You might say, however, that I am limiting the reusability of my code.  I'd argue that proper separation of concerns shields me from this.  I have never reused data access codes across projects since the data model always differs.

Now, the game changes if I'm building a product.  In this case an ORM is, by far, the best way to support multiple DB platforms.  It's worth noting that even with an ORM, there's still a lot of plumbing and data containers that the ORM maps which should be generated.  Anyone that is hand-writing files that correlate to a database table need are stealing from their customers. 

In the end, this comes down to using the right tool for the job.  I feel that code generation of potentially native SQL is the right tool for a single-db-platform website and, in contrast, ORMs are the right tool for shippable products that can live on any platform.  In both cases, though, code generation should play a role in the development process.

About Me

thumbnail I'm a software developer currently employed by Pearson (PSO/PSON)* where I work with, my passion, .NET.  I have (close to) two decades of programming experience and I'm constantly trying to learn new languages, technologies, practices, etc.

 

Disclaimer

* Emerle.net is owned and operated by Ryan Emerle. The views expressed on this blog are his personal opinion and do not necessarily reflect the views of his employer or clients.

The same holds true for comments posted to Emerle.net; they are the comment posters' personal opinion and do not necessarily reflect Ryan Emerle's views or the views of Ryan's employer or clients.