Archive for January, 2008

XPO and Instance scopes in autofac

Sunday, January 13th, 2008 | Snippets | 1 Comment

One of the appealing ideas in the autofac is scope nesting and explicit life management of the component instances.

Imagine the situation of the task server, where every task depends on a wide variety of the services. Let us take “Session” as an example. It could be registered in the container with the following lambda expression:

this.Register(c => c.Resolve<IServerConnector>().GetSession()).
  As<Session>().
  WithScope(InstanceScope.Container);

Note, that the actual component being registered is a Session factory that resolves some IServerConnector and produces instances with the scope of their container. The container will have only one session and it will be disposed when the container itself get disposed.

Additionally note that this lambda resolution is faster than the reflection, so we can use it for the micro-scopes.

The tasks could be registered in a ITaskRegistrar (just a simple List<Func<IContext, ITask>> for this situation) using the same lambda syntax:

ITaskRegistrar resolve = container.Resolve<ITaskRegistrar>();

resolve.Register(c => new ProcessApprovedApplications(c.Resolve<Session>()));
resolve.Register(c => new RetrieveQueuedResults(c.Resolve<Session>()));

IServerConnector and ITaskRegistrar get registered in the xml configuration file along with modules that contain the component registrations mentioned above.

Then the simple task server itself could be written like this:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new ConfigurationSettingsReader("core"));

using (Container c = builder.Build())
{
  foreach (Func<IContext, ITask> func in c.Resolve<ITaskRegistrar>())
  {
    using (ITask task = func(c))
    {
      task.Execute();
    }
  }
}

In this scenario all tasks share the same scope and the Session instance within.

In order to make every task use its own session (i.e.: for the purposes of making them thread-safe), we could slightly modify the code:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new ConfigurationSettingsReader("core"));

using (Container c = builder.Build())
{
  foreach (Func<IContext, ITask> func in c.Resolve<ITaskRegistrar>())
  {
    using (Container taskScope = c.CreateInnerContainer())
    using (ITask task = func(taskScope))
    {
      task.Execute();
    }
  }
}

And if you want to keep the single session per container, but give the tasks separate UnitOfWork instances (provided UnitOfWork inherits from Session), then you could use the first program snippet but change the Session registration routine to:

this.Register(c => c.Resolve<ServerConnector>().GetSession()).
  As<Session>().
  WithScope(InstanceScope.Container).
  Named("session");
this.Register(c => c.Resolve<Session>("session").BeginNestedUnitOfWork()).
  As<Session>().
  WithScope(InstanceScope.Factory);

Basically here we intercept the requests to Session and return transient UnitOfWork instances instead.

Tags: ,

Organization of xLim solutions: development, svn and integration

Saturday, January 12th, 2008 | Articles, Uncategorized | 1 Comment

In my last article for the xLim 2 series I’ve talked about some simple development principles that proved to be effective in the implementation projects. In this post I’ll start describing the common solution structure that was established in that process.

Note, that I will not explicitly address database management in this structure (folder for the db-create, chained revision-based .cs and .sql upgrade scripts etc), since the XPO manages most part of the complexity here.

Below you will find the folder structure for the root of your version control repository.

SVN:\

  Doc                   - development-related docs
    000 Global          - "Global" contains all
    001 Initialization    guidelines, MSP files,
    002 Project Planning  project scope/chapter etc
    003 Prototyping     - numbered folders form up
    004 Milestone 1.0.0   the simple timeline
    ...
  Extension             - extensions are kept and
    CRM                   managed separately. "System"
    E-Forms               distros go into "Resources"
    ConstructionPM        in a binary form
  System -->            - xLim framework
  Prototype             - those are better than UCs
    001 SimpleCAB         and represent excellent
    002 Web IoC           knowledge-base material
    003 DxGridSchema      for new developers.
    004 Workflows
    ...

Here’s the generic organization of the “System” folder (that’s the core sources for the specific xLim 2 implementation). The extension projects also have similar structure.

SVN:\System\

  branch                - development branches, if needed
  distribute            - CC.NET releases into this folder
    1.0.0.23              X.Y.Z.Revision format
    1.0.1.45
    1.0.2.92
    ...
  tag
    1.0.0.1             - X.Y.Z.Revision format for every
    1.0.0.2               successful commit (autocreated
    1.0.0.3               by the integration server)
    ...
  trunk -->

Note, that it is a good idea to place some restrictions on the trunk folders from the very start (if you are using Subversion). Here are the switches that we normally setup:

  • svn:ignore
  • tsvn:logminsize (20-40 characters is enough)
  • bugtraq:warnifnoissue
  • bugtraq: logregex (it is enough to set “#(\d+)” pattern to make any #BugId number recognizable by both TortoiseSVN and Trac)
  • bugtraq:url (for the purposes of trac integration this points to the tickets path and allows you to open referenced tickets by just clicking on the number in the TortoiseSVN log)

SVN:\System\trunk\

  Help                 - help templates and articles
  Resource             - everything that's needed to build
    Dxperience           fresh check-out on a new machine
    Castle               is here (except .NET SDKs).
    EntLib               The same rule applies to the
    Images               specific extensions as well
    NAnt
    NUnit
    7za.exe
  Source                    - that's just the sample. It
    xLim.Client.Core          will described below.
    xLim.Client.DxCore
    xLim.Client.Interface
    xLim.Client.Host
    xLim.Server.Core
    xLim.Server.Host
    xLim.Server.Interface
    xLim.Server.WebServices
    xLim.Shared.Business
    xLim.Shared.Core
    xLim.Shared.Data
    xLim.Shared.Interface
    xLim.Web.Core
    xLim.Web.DxCore
    xLim.Web.Host
    xLim.Web.Interface
    GlobalAssemblyInfo.cs     - you keep those shared and
    VersionAssemblyInfo.cs      accessible, do not you?
  Test                        - unit tests per project
  Tool                        - some tools that could make
    DeploymentAid               development and maintenance
    NavigationBuilder           more simple and efficient
    SchemaTool
  xLim.Core.sln
  xLim.Core.build             - NAnt build file
  go.cmd                      - simply calls Resource/Nant
  Farmenu.ini                   for the build file

This is how the development checkout copy is usually organized for multiple solutions.

Working folder (i.e.: E:\Projects\xLim):

  Docs                        - check-out of the documents
  xLim.ConstructionPM         - check-out of the CPM trunk
  xLim.CRM
  xLim.System                 - check-out of the System trunk
    Build                     - this folder is autocreated

Here’s the simple folder structure for the xLim 2 integration server.

Integration:\

  Logs                        - rolling logs of CC.NET
  xLim.CPM                    - separate folder per solution
  xLim.CRM                      being built
  xLim.System
    Artifact                  - CC.NET build artifacts
    Build                     - NAnt works here
    Distrib                   - integration server creates
      1.0.0.23                  distributions here and adds them
      1.0.1.45                  to the SVN. Normally "Distrib"
      1.0.2.92                  is accessible via secure FTP
      ...
      lastversion.txt         - simple, but helps to automate
    State                     - CC.NET state information
    Trunk                     - Working copy
  ccnet.config                - the name speaks for itself

A word on the changes. The development cycle of the main project is separate from its extensions (that’s convenient for medium-sized development projects and teams). Extensions use the “Interface” and “Core” libraries from the main xLim project (those are distributed in a form of packaged APIs and are stored in “Resources” folder in the binary form).

Additionally the integration server could package the extensions in one complete setup file along with the corresponding version of the actual application hosts (Server, Desktop or Web). That’s where Integration:\xLim.System\Distrib\[Version] are come in handy.

In my next post I’ll concentrate on the logical structure and the internal dependencies of the actual “SVN:\System\trunk\” Visual Studio solution.

Tags:

Some more insight into the autofac

Thursday, January 10th, 2008 | Snippets | 1 Comment

Here are some updates:

  1. The code required to compile autofac against .NET 2.0 (in a single file) could be located here.
  2. As Nicholas pointed out, there is no need to register parent scope or do something exceptional about the lambda expression. The expression already evaluates against the current scope. This nicely deals with the previous Castle MicroKernel problem described here (what’s more important, it is easy to understand what and why happens behind the curtains). See his snippet below
ContainerBuilder cb = new ContainerBuilder();
cb.Register(c =>; new A(c.Resolve<B>())).
  WithScope(InstanceScope.Factory);

Container parent = cb.Build();

Container child = cb.CreateInnerContainer();

var childBuilder = new ContainerBuilder();
childBuilder.Register(c => new B());
childBuilder.Build(child);

A a = child.Resolve<A>();

More updates are to come. I’ll try to check out the following areas of the autofac IoC:

  • XML configuration (nothing exceptional is expected, but still you never know)
  • Lifestyles and scopes
  • Possibility of implementing the policy injection with the autofac (may be lambdas would aid a little bit here too…). It is always nice to know if you can route all your business objects through some fast IoC.

Tags: ,

One more interesting and fresh .NET IoC container: autofac

Thursday, January 10th, 2008 | Articles | 4 Comments

Recently I’ve stumbled upon the autofac IoC container.

This container creates an impression of being more flexible and lean than the Castle, StructureMap, and the ObjectBuilder. Additionally, it is supposed to provide inherently good performance, scope and disposal handling.

Well, if the container uses lambda expressions as one of the options to register components, that already tells something about the approach (yes, this means “no Constructor reflection”). If everything is at this level then theoretically we could be talking about cheap and numerous MicroScopes here.

Given that, the autofac could be a better alternative for the Castle in xLim 2 solution.

One usability problem for xLim 2 lies within the .NET framework incompatibility. xLim 2 itself is restricted  to 2.0 for a number of reasons; autofac uses 3.5 and VS 2008.

This turned out to be just a small obstacle. In my last post I’ve spoken about using .NET 3.5 features for the .NET 2.0. With that, it took only 10 minutes to compile the sources against .NET 2.0. I’ve simply copied a big chunk of the “System.Linq.Enumerator, System.Core.dll” extension class into the solution. It compiled and passed all the tests flawlessly.

However it took a little bit more time than that to start playing with the container (it is curious that the biggest efficiency drain during these 90 minutes was the absence of the Resharper in the fresh install of VS 2008).

I’ve prototyped a couple of primary usage scenarios and the first impression is that autofac is capable of handling the xLim 2 better than the Castle MicroKernel/Windsor Container currently does (of course there should be more solid testing before the actual replacement would be seriously considered).

The strongest argument against the autofak is that it does not have solid community around it and thus there is no solid production background. In fact, it is being developed right now by Nicholas Blumhardt. However the last point does have some appeal to it, since small systems/groups always seem to have more flexibility and mobility (that’s due to lower inertia and decision-making lags).

Additionally I was not able to get a quick answer for the question in this post. In short the problem is like this:

  • A depends on B;
  • A has a transient lifestyle (every time a new instance could be created);
  • A is registered in the parent scope;
  • B is registered in the child scope;
  • how do we resolve A in a child scope?

Of course there could be somewhat straightforward solution like this:

  • Register parent scope as component in every child scope
  • Register A with the lambda expression that will dig get the parent expression and resolve the dependency.

Although this approach is close in spirit to the self-replicating nanorobots, it just does not feel right.

PS: Next post on autofac contains link to .NET 2.0 compatibility .cs file. This file is all you need in order to compile autofac to target .NET 2.0.

Tags: , ,

How to use .NET 3.5 syntax and compiler features for .NET 2.0?

Thursday, January 10th, 2008 | How To, Snippets | 3 Comments

I’ve just squeezed out a couple of hours to install and try Visual Studio 2008 today. There were two surprises that came with that:

  • Unpleasant - Resharper does not fully support .NET 3.5 (it almost hurts). It is planned to have R# 4.0 release around 2008 Q1.
  • Pleasant - Some .NET 3.5 compiler and syntax sugar features work with .NET 2.0.

Let me expand on the last item. These .NET 3.5 features work with .NET 2.0:

  • local variable inference
  • anonymous types
  • object initializers
  • extensions methods
  • query expressions
  • lambda expressions

In other words, this code does compile in Visual Studio 2008 when .NET 2.0 framework is targeted:

public static class Program
{
  static void Main(string[] args)
  {
    List<Customer> customers = new List<Customer>
    {
      new Customer{Name="Bob", Age=23},
      new Customer{Name="Donald",Age=10}
    };

    var query = from c in customers
                where c.Age &gt; 11
                select c.Name;

    query.Print();
  }

  public static void Print<T>(this IEnumerable<T> collection)
  {
    foreach (T item in collection)
    {
      Console.WriteLine(item);
    }
  }
}

public class Customer
{
  public string Name { get; set; }
  public int Age { get; set; }
}

To make this happen you just need to add the following namespace and class declarations:

namespace System
{
  public delegate TRes Func<TSrc, TRes>(TSrc src);
}
namespace System.Runtime.CompilerServices
{
  public class ExtensionAttribute : Attribute { }
}

namespace System.Linq
{
  public static class Enumerable
  {
    public static IEnumerable<TSrc> Where<TSrc>(
      this IEnumerable<TSrc> source, Func<TSrc, bool> predicate)
    {
      List<TSrc> res = new List<TSrc>();
      foreach (TSrc s in source)
      {
        if (predicate(s))
        {
          res.Add(s);
        }
      }

      return res;
    }
    public static IEnumerable<TRes> Select<TSrc, TRes>(
      this IEnumerable<TSrc> source, Func<TSrc, TRes> selector)
    {
      List<TRes> res = new List<TRes>();
      foreach (TSrc s in source)
      {
        TRes t = selector(s);
        res.Add(t);
      }

      return res;
    }
  }
}

And if you remove the code above (i.e.: using C# preprocessor directive #if), and switch then target framework to .NET 3.5, the program will still compile.

It is sweet, is not it?

If this works as it is expected I’d be glad to have those features in .NET 2.0 projects. This will help to produce more efficient code.

Update: In the next post I’ll explain how to compile autofac project (it extensively uses lamda expressions and extensions) against .NET 2.0. And there’ll be some compatibility code in a single file.

Update: alternatively you can use LinqBridge library to compile against .NET 2.0 or simply manually reference System.Core.dll (requires editing of project file).

Common development principles for xLim

Tuesday, January 8th, 2008 | Articles | No Comments

In the previous post on xLim 2 I’ve talked about the software requirements and recommendations for this kind of architecture solution (IDE, components, libraries and tools).

In this post I’ll attempt to cover briefly major guidelines and principles that proved useful for this approach.

The following principles are recommended to be followed for the efficient xLim 2 development:

  • Employ version control and continuous integration (using only dedicated server for the releases)
  • Great deal of xLim solutions’ business value is stored in the specific configuration settings (i.e.: schema files, configuration presets for the GridView handlers, layout presets for the single editors, permission settings and workflow chains). They also should be included in the version control and continuous integration.
  • Employ test-driven development where appropriate (i.e.: UI handlers and controllers would benefit from the unit tests, workflow micro-controllers are too straightforward to be tested).
  • It should take less than 30 minutes on a new machine to setup integration environment, get the sources, compile xLim 2, test it and initialize specific pre-configured solution.
  • Develop xLim system vertically not horizontally (create and deploy into production simple full-layered solution first, and then start extending it).
  • Stick to the Don’t Repeat Yourself principle (refactor and reuse code, controllers and handlers where appropriate)
  • Perform rapid prototyping in the first phase of the software development project and then follow by the iterative development (2 week development phases with planning of 2-3 phases into the future). Planning should include logically working through all the changes-to-be-implemented and aligning them with the evolution of the architecture.
  • Always schedule time for xLim configuration and tuning after each milestone.
  • Regular backup policy should obviously be in place.
  • Do not waste time writing throw-away use cases that are used only for formal acceptance. It is more efficient to stay in close contact with the customer and understand his real business requirements.
  • Writing composite business functionality overviews and visualizing workflows, on the other hand, is recommended. xLim is extremely flexible, so it is too easy for the customers to get lost in their own choices about configuring views, workflows and the security. Composite overviews and workflow maps will serve as an excellent way of staying on the same page and initial documentation.
  • xLim 2 solutions do not favor big resource pools and parallel distribution of tasks. That’s because of the complex nature of the solution. This implies greater development risks and the need to manage them carefully.
  • Do not implement configurability and flexibility just for the sake of doing that. I’ve seen good information management systems turn into an unmaintainable and logical mess, just because they were made too flexible. Flexibility requires separate management UI and adds additional fragile points in the system.
  • Work closely with the end-users. xLim 2 is extremely flexible, so they should get the feeling/understanding of the functionality that is easy to achieve (i.e.: adding new business objects with the grids and complex workflows) and is not so easy (i.e.: adding completely new type of shared object that requires complex web and desktop UI handlers).

Additionally, here are the references that proved themselves to be quite useful while establishing the guidelines for the specific xLim solutions and introducing new developers to them:

Although the XPO takes care of the 80% of database management, the remaining 20% still require some attention. Here’s the recommended reading on that:

In the next post on xLim 2 I’ll get closer to the development specifics of the actual solutions: recommended folder structure for the development, SVN and integration purposes; build scripts and change propagation in the big solutions.

Tags:

How to simplify complex maintenance tasks of your information management solution

Saturday, January 5th, 2008 | Uncategorized | 1 Comment

Here’s one more advantage of having universal (and secure) data gateway service on the server side (I’m talking about the xLim approach again): you can easily write small or large tools that simplify complex maintenance tasks.

2008-01-05_180825

Basically you can consider this console application to be an extremely light-weight client for the xLim 2 server architecture.

The advantages of this approach (as opposed to working directly with the database):

  • The tool will have the access rights to the database that derive from the login permissions, audit log will have all events recorded for this login, all the workflows (if invoked) will be initiated by this login also (if there are permissions)
  • You get low-level access to the database, but there is still no SQL to write.
  • You can perform high-level operations that are not easy to do in the SQL (like spell-checking all Forms against MS Word dictionary)
  • Imagine live system that uses XPO distributed caching. Normally it is not a good idea to work directly with the database, since all the changes go directly without even touching the cache. You’ll have to connect to the server anyway, since the cache will need to be notified of the changed tables. This approach, on the other side, already routes all the changes through the cache and the system will automatically stay consistent (actually the xLim2 server should not even expose the gateway to IDataLayer, but rather the cache communications, so it would be impossible to work without notifying the cache)
  • In some hosting scenarios the database is not accessible outside the server. This approach does not need the direct access anyway - the gateway would do it.

Tags: ,

RSS

Search

Archives