Archive for February, 2008

How to avoid tight IoC coupling in non-deterministic resolution scenarios?

Normally IoC should never go into the code below the level of module/component registration. That’s the rule.

But what if some specific component needs to resolve components based on some conditions (i.e. resolving by name when name is passed externally)?

You can use dictionary if the components are singletons, but this would not work if they have to be resolved in the current scope. For example, we might need to execute some workflow class knowing only its name and interface. And some workflow class (neither we know, nor do we care) could just need to access the data store within the scope of the current session.

These simple interface declarations help me to manage scenarios like this with a couple of lines of code, while keeping the IoC intrusion minimal:

public interface IResolver<Param, Object>
{
  Object Resolve(Param param);
}

public interface IResolver<Object> : IResolver<string, Object> { }

Additionally there is a simple class to lend IoC to the components with inlining:

public class Resolver<Param, Object> : IResolver<Param, Object>
{
  private readonly Func<Param, Object> _function;

  public Resolver(Func<Param, Object> function)
  {
    _function = function;
  }

  public Object Resolve(Param param)
  {
    return _function(param);
  }
}

public sealed class Resolver<Object> :
  Resolver<string, Object>, IResolver<Object>
{
  public Resolver(Func<string, Object> function) : base(function)
  {
  }
}

With that you can register named resolution of some interface (ICommand, for example) with this nice statement:

builder.Register(scope => new Resolver<ICommand>(
  name => scope.ResolveByName<ICommand>(name)))
  .As<IResolver<ICommand>>()
  .WithScope(InstanceScope.Container);

and then it could be later used in any component like

public sealed class TaskExecutor
{
  private readonly Resolver<ICommand> _commands;
  public TaskExecutor(Resolver<ICommand> commands)
  {
    _commands = commands;
  }

  ...
  _commands.Resolve(commandName).Execute();
  ...
}

Remarks:

  • The resolution interfaces should always be explicitly written. That’s just to keep the code under control.
  • This function-based resolver interface simplifies unit testing quite a bit (especially if you use MockContainer).
  • Do not try this code at home with your IoC container unless this container is Autofac.
  • Using some global static class (i.e.: IoC.ResolveByName…) is not a valid solution either, because:
    • That’s global static class and its usage just complicates code management and testing
    • Static resolution would not have any clue about the current scope (rendering it useless)

Why do not we resolve delegates in IoC?

Do you see the difference between these two declarations of some imaginary command?

public sealed class DeleteCommand : ICommand
{
  private readonly IRecordSelector _recordSelector;
  private readonly IMessageBoxService _messaging;
  private readonly IRecordManager _recordManager;

  public DeleteCommand(IRecordSelector recordSelector,
    IMessageBoxService messaging, IRecordManager recordManager)
  {
    _recordSelector = recordSelector;
    _messaging = messaging;
    _recordManager = recordManager;
  }

  public void Execute()
  {
    List<XPObject> records;
    if (_recordSelector.TryGetOneOrMoreRecords(out records))
    {
      if (_messaging.Ask("Do you really want to delete '{0}' records?",
        records.Count))
      {
        _recordManager.Remove(records);
        _recordSelector.RefreshData();
      }
    }
  }
}

and this one

Action<IRecordSelector, IMessageBoxService, IRecordManager> command =
  (selector, messaging, manager) =>
{
  List<XPObject> records;
  if (selector.TryGetOneOrMoreRecords(out records))
  {
    if (messaging.Ask("Do you really want to delete '{0}' records?",
      records.Count))
    {
      manager.Remove(records);
      selector.RefreshData();
    }
  }
};

Class version is longer but it can be resolved in IoC. The delegate is more concise but it does not resolve.

So, why do not we resolve delegates in IoCs?

PS: additional difference is that if command is stateless then it could be resolved only once in the IoC scope and the subsequent executions will use “cached” version (Container scope instead of Factory could be used). But I’d trade that for the DRY principle.

xLim 2 Engine concept or simple continuous integration for businesses

xLim 2 Engine is an extremely simple concept and continues the idea from post on “How to simplify complex maintenance tasks of your information management solution?“.

So, if you have architecture like this, you can just:

  • take multiple maintenance and automation tools of yours
  • throw out all the repetitive code (connection, logging, security, etc) and wrap everything that remains with some common interface (ICommand or Action<IContainer> are equally fit here)
  • Create some simple host (Win Service, Mono daemon, Console Application) that establishes an IoC environment by loading the shared assemblies (by just asking the shared module to register), then resolves every command in a dedicated scope and runs it.

Since the commands are just ordinary IoC components, you can configure them in some XML file and provide the parameters. The resulting config file will resemble NAnt build file quite a bit. The only difference is that you are playing with business objects, workflows and services instead of some low-level development entities.

And since the engine talks to the main server via the common gateway interface (and uses some access account for this), you can be sure that

  • all possible harm will be limited by the permissions defined by the account
  • logging and audits will be applied

We recently had to implement similar automation engine for the current xLim 2 implementation. That was extremely easy with this concept, since all we had to write was the engine host (200LOC for the console implementation) and the actual command logic. Shared modules lent us all the other required functionality (and even a couple of ICommand implementations were reusable)

Now, you’ve just got your simple business integration engine. Adding new tasks is trivial here, since you have to worry only about the actual code (the engine and IoC will DI all the required interfaces from the shared modules). Given that, you can easily:

  • Send warning if some system goes short on DB or HD space
  • Save sales numbers every 1 hour to capture the statistics for future analysis
  • Fire alarms if some KPIs go out of range
  • Send message to admin if that document processor service is not responding again
  • Alert developers if there are any exceptions in the server log

It is an interesting coincidence that Ayende had written about the continuous validation concept in his web log. That fits quite close in this picture, although I believe he mixes two different concepts that logically should be separated: Environment Validation Framework and the Automation Engine.

Basically, the validation framework is just some IValidationReporter interface that is supported by some singleton components living in the root scopes of the application being validated. And then there is some component that generates composite validation report per request and sends it to the external monitoring system.

Now, why do we want to separate environment validation from the engine? These are the reasons:

  • System might not have the components/interfaces for running regularl environment validation checks and then taking some actions based on complex logic (do you want to add that extra code in there just for that?)
  • Configurations of different systems might have different ways of going invalid (i.e.: some systems could have recommended HD limit of 40Mbs while others could be limited to 40GBs, some could require access to dedicated workflow server and some could just live without that). You would not to spread that info with every config.
  • Some failures could be detected only after being aggregated (i.e. work cluster could be considered to be in invalid state if all nodes are consistently overloaded)
  • Some failures could be linked to external systems (i.e. HD space allocation for the user depends on type of the account of his company)

So it seems to be more efficient to have dedicated automation engines (you could have as many of them as you want) to handle all the meta-system logic, while leaving only report generation to the actual system being monitored.

Using skins to distinguish between different build/configuration types

The most appealing way to distinguish between development, test and production versions of your desktop and web applications is to use different skin for each one.

Normally, people tend to miss connection strings, application titles or version numbers. Or, it could be an extra burden for non-dev people to memorize things like: “If there is TEST within the title bar and the connection string in the status bar points to http://test…, then this is snapshot and you can do whatever you want to.”

If the entire application has nice Caramel skin for the test version and professional Office outfit for the production, then it would be quite hard to get confused with that.

DifferentSkins

All you need is:

  • Integration server managing “Test” and “Release” releases (and any other type of build)
  • Different config sets under version control (normally these should be stored in a secure SVN repository separately from the “Trunk”)
  • Component suite that supports simple skinning (like DevExpress)
  • Some flexible configuration system (Autofac’s own config is perfectly fine for this purpose)

If you have all these (and you normally should) then it would take just 10 minutes to enable “different UI look for different build type” feature.

Memo to self: thoughts on xLim, autofac and business functionality

Just a number of things to think about when there is time:

  • Write a post on XAF improvement possibilities
  • Push the MockContainer for autofac out of prototypes.
  • Impement ILog factory for the autofac (and merge concepts of ILog, LogManager and LogScope, if possible).
  • Add Mono testing for autofac (just re-run Nick’s tests under Windows+Mono)
  • Implement FileStore for the xLim and do some stress testing of Web+Server+Desktop+Engine on dev hosting (CrystalTech $2,95 per month ASP.NET account)
  • Implement Business status reports (aka “NUnit for business“) as xLim 2 module
  • Add maintenance tasks to xLim.Engine
  • Play with defining some business performance indicators and add a task to take regular snapshots of these by Engine (i.e.: for forecasting, analyzing, nice visualization, alerts)

Running xLim with latest Mono: XPO, autofac and binary compatibility

This is the update to the previous R&D post on running xLim (XPO+Autofac) under Mono 1.2.6.

Short summary:

  • Latest autofac code passes all tests with the latest mono sources
  • The dictionary issue (the one that required patching XPO sources) is fixed in the latest mono code
  • Binary remoting does not work for XPO purposes.

The reason for the last problem is simple: Mono and .NET implementations of the DateTime object are completely different. Serialized Mono DateTime uses more bytes than .NET implementation. The first one does not implement ISerializable, while the last one - does. That could make some difference.

Miguel de Icaza has pointed to the topic in Mono FAQ on the subject of binary compatibility between .NET and Mono. It turns out that the DateTime is not one of these compatible types. I wonder if there are other incompatible primitives or widely-used classes.

ReSharper 4.0 EAP - Nightly builds are available for download

You can download nightly builds of ReSharper 4.0 to start working with these features (as quoted from the roadmap):

  • Support for both Visual Studio 2005 and 2008
  • Comprehensive support for C# 3.0 language features, including:
    • New code analysis, context actions and quick-fixes
    • New refactorings (such as Convert to Extension Method, Convert to Automatic Property, Convert Anonymous Type to Named)
    • Updated IntelliSense
  • Many more intelligence and productivity features
    • Full set of refactorings available for VB.NET
    • New quickfixes and context actions for XAML files
    • Referenced assemblies are now taken into account in null-reference analysis thanks to external annotations. ReSharper is packaged with annotations for the .NET Framework assemblies
    • Code Cleanup — a tool for ensuring compliance with code guidelines and enhancing code structure
    • Complete Statement — a feature that will complete language constructs and get you ready to write the next statement
    • Many other enhancements and new features throughout the product

Update: ReSharper 4.0 feels to be a terrific aid in the development (esp. when compared with working on VS 2008 with 3.1). The only decent problem is that the solution-wide analysis marks extension methods as errors if there is no reference to System.Core (i.e.: using LinkBridge.dll to compile towards .NET 2.0). Ilya has created an issue that could be tracked here.