Sergey Shishkin

on agile software development

Archive for the ‘Development’ Category

Mono as a lightweight .NET runtime

How big is .NET 3.5 runtime? The full redistributable package for x86, x64 and ia64 platforms including 2.0 and 3.0 is about 200 MB. Not a single user needs to download and install it all: somebody already has 2.0 or maybe even 3.0, and nobody is going to install all the supported architectures (x86 etc.) on a single machine. So this huge download is only intended to be distributed on a CD or DVD with applications requiring .NET, when you don’t know in advance what platform you are targeting. If you do know the user’s platform in advance, you can downstrip the package down to some 20-60 MB. Which is pretty good.

Anyways .NET Framework has to be installed using Windows Installer, and it’s a quite invasive way of deploying an application. Can somebody XCOPY-install .NET Framework? I suppose it to be very tricky if possible at all. And we have those copyrights and license agreements saying that Windows Installer is the only legal way to deploy .NET runtime to users.

All this problems might seem illusive, since Microsoft is pushing .NET Framework through Windows Update and starting from Windows XP SP3 and Vista RTM users get at least .NET 2.0 installed. But the e-health market, my company works in, is very conservative (at least in Germany) and users are still running Windows 2000 with windows apps emulating DOS-like GUI. It is horrible! We can not rely on any Windows Updates or even a live and fast internet connection to run the .NET Framework setup bootstrapper. Moreover, our software, a web service, should be deployed as an integrated component into some third party application (almost definitely not a .NET one). And the more complex our deployment story is, the less partners would want to embed our software into their products.

Are there any alternatives out there?

One can turn to virtualization solutions. But instead of hardware virtualization, one can virtualize the .NET runtime. Using Xenocode Postbuild it is possible to compile a managed application into an unmanaged one with embedded fully functioning .NET runtime. The size of an app starts from 11 MB for a simple Hello World App and is from 40 MB in a real world scenario (without deleting unused .NET code, so that reflection can work properly). And this is pretty good, although not cheap.

Here comes Mono

There is also the Mono Project out there, which contains an open source runtime compatible with .NET CLR on binary level. It means that you can run apps compiled for .NET CLR on Mono CLR without recompilation. Mono’s cross-platform nature makes it much simpler in what it means to deploy the runtime. You just have to fulfill the requirements of the LGPL or obtain a commercial license from Novell.

How it works?

So I downloaded and installed the full Mono for Windows package and started to play with it. My aim was to get a minimal subset of Mono to be able to run the Mono’s XSP development web server and its test web site (\lib\xsp\test\).

The result is the following structure of 45 files only 21 MB in size total:

\bin\libglib-2.0-0.dll
\bin\libgthread-2.0-0.dll
\bin\mono.dll
\bin\mono.exe
\bin\run.cmd
\etc\mono\2.0\Browsers
\etc\mono\2.0\DefaultWsdlHelpGenerator.aspx
\etc\mono\2.0\machine.config
\etc\mono\2.0\settings.map
\etc\mono\2.0\web.config
\etc\mono\2.0\Browsers\Compat.browser
\lib\mono\2.0\Accessibility.dll
\lib\mono\2.0\gmcs.exe
\lib\mono\2.0\gmcs.exe.config
\lib\mono\2.0\Mono.Data.Tds.dll
\lib\mono\2.0\Mono.Messaging.dll
\lib\mono\2.0\Mono.Posix.dll
\lib\mono\2.0\Mono.Security.dll
\lib\mono\2.0\Mono.Web.dll
\lib\mono\2.0\Mono.WebBrowser.dll
\lib\mono\2.0\Mono.WebServer2.dll
\lib\mono\2.0\mscorlib.dll
\lib\mono\2.0\System.Configuration.dll
\lib\mono\2.0\System.Configuration.Install.dll
\lib\mono\2.0\System.Core.dll
\lib\mono\2.0\System.Data.dll
\lib\mono\2.0\System.Data.Linq.dll
\lib\mono\2.0\System.dll
\lib\mono\2.0\System.Drawing.dll
\lib\mono\2.0\System.EnterpriseServices.dll
\lib\mono\2.0\System.IdentityModel.dll
\lib\mono\2.0\System.IdentityModel.Selectors.dll
\lib\mono\2.0\System.Messaging.dll
\lib\mono\2.0\System.Runtime.Serialization.dll
\lib\mono\2.0\System.Security.dll
\lib\mono\2.0\System.ServiceModel.dll
\lib\mono\2.0\System.ServiceModel.Web.dll
\lib\mono\2.0\System.Transactions.dll
\lib\mono\2.0\System.Web.dll
\lib\mono\2.0\System.Web.Extensions.dll
\lib\mono\2.0\System.Web.Services.dll
\lib\mono\2.0\System.Windows.Forms.dll
\lib\mono\2.0\System.Xml.dll
\lib\mono\2.0\System.Xml.Linq.dll
\lib\mono\2.0\xsp2.exe

It is still far from perfection (why ASP.NET applications need System.Windows.Forms, for example), but it is a good proof of concept. I’m only a newbie to the whole world of Mono. But now I can start a web site on a windows machine without any .NET Framework installed from a website folder just like this:

..\mono-mini-2.6.1\bin\run.cmd ..\mono-mini-2.6.1\lib\mono\2.0\xsp2.exe –root . –port 8080 –applications /:.

In order to make it repeatable, I made a batch script that creates this Mono-mini package out of a real Mono installation. It can be used like this:

mono-mini.cmd c:\work\ExternalBin\Mono-2.6.1 c:\temp\mono-mini-2.6.1

Summary

I’ve got an XCOPY-deployable .NET runtime for my ASP.NET web services with 3.5 support in under 21 MB (7.5 MB zipped) which works on my machine 🙂 What now?

  • I need to test it thoroughly with the apps I will run on it. It is still possible that some components are missing.
  • Also I might remove the Windows Forms dependency but it would require me to patch the machine.config and the global web.config though.
  • All this bin\, lib\, etc\ coming from the linux-background of Mono could easily be simplified for the Mono-mini package.
  • Some licensing questions are yet to be clarified. When licensed under LGPL, Mono is not allowed to be embedded into a non-LGPL executable, AFAIK. So, making deployment even more simple with Xenocode (only as an assembly repackaging solution) or .NETZ (for the same purpose) is not possible without purchasing the commercial license from Novell.
Technorati Tags:

Advertisements

Written by Sergey Shishkin

24.12.2009 at 20:41

Posted in Development

The Rx Framework – Linq2Events

That’s cool:

IObservable<Event<MouseEventArgs>> draggingEvent =
     from mouseLeftDownEvent in control.GetMouseLeftDown()
     from mouseMoveEvent in control.GetMouseMove().Until(control.GetMouseLeftUp())
     select mouseMoveEvent;

Jafar Husain’s blog contains all the details.

Technorati Tags: ,,

Written by Sergey Shishkin

24.07.2009 at 15:51

Posted in Development

Architecture.NET Open Space

The last weekend I participated in my first open space (anti)conference – Architecture.NET Open Space in Düsseldorf. And I must say: It was my best conference experience ever!

There are some results in the conf’s wiki in German. Here I just want to write down some of my observations.

A couple of things came up in almost every session:

  • Clean code and agile design principles. Software architecture consists of decisions that are hard to change. Agile software architecture aims to make changeable as many decisions as possible. So clean code and agile design principles is the absolute minimum that we don’t want to trade off. This statement is not a dogma – it’s the cornerstone that makes other decisions changeable, it makes agile software architecture possible.
  • Asynchronous communication and messaging. This is a very hot topic now. Messaging is what enables the Open/Closed Principle on the architectural level. And O/CP is what enables architecture to evolve and does not let it rot.

Discussions were sometimes heated and controversial, but always very inspiring and thought-provoking. I already count days till Archnet Open Space next year.

Technorati Tags:

Written by Sergey Shishkin

08.06.2009 at 01:12

Posted in Development

Intentional Software Demo

I just watched a great demo of Intentional Domain Workbench presented at DSL DevCon about a month ago. Beside the fact that the demoed software frightengly looks like a “silver bullet”, "The Holy Grail” or at least “the future” of software development, it is the first demo of a RAD tool I saw that mentioned automated tests integration. See for yourself, it looks a lot like FIT acceptance tests:

Enjoy the full video at MSDN. It’s just awesome!

Written by Sergey Shishkin

05.05.2009 at 11:06

Posted in Development

Data Access Patterns @DNUG Cologne

Yesterday, during the 30th meeting of .NET UG Cologne, I gave a mini demo-talk on the Repository and Specification patterns for Data Access. There were no slides, just code.

What Is It All About?

I like to write as little code as possible and be able to write as simple code as possible. Especially when it comes to Data Access. This is what I want my Data Access code looks like:

var price = new ProductPriceRangeSpecification(300m, 500m);

var name = new ProductNameSpecification("Road Frame");

 

var products =

    (from p in repository.FilterBy(price.And(name.Negate()))

    orderby p.Name

    select p)

        .ToList();

How It Works?

The main character here is the Repository. I tried to keep its interface as small as possible (and it is still the biggest interface in the system):

public interface IRepository<T>

{

    void Save(T entity);

 

    void Delete(T entity);

 

    T Get(object key);

 

    IQueryable<T> AllEntities();

}

That’s really it. The rest of querying functionality will be added through extension methods. Here is where the FilterBy method comes from:

public static IQueryable<T> FilterBy<T>(

    this IRepository<T> repository,

    ISpecification<T> specification)

{

    return specification.Filter(repository.AllEntities());

}

I use extension methods extensively and don’t think I abuse them. In this case I clearly separated the contract needed to be implemented and the publicly available functionality built on top of it. Extension methods basically help to build a DSL around a very simplistic object model. And whenever I wonder where a method comes from, I hit F12.

Specifications appear on scene in supporting roles every here and there:

public interface ISpecification<T>

{

    Expression<Func<T, bool>> GetPredicate();

}


public
class ProductNameSpecification : SpecificationBase<Product>

{

    private readonly string query;

 

    public ProductNameSpecification(string query)

    {

        this.query = query;

    }

 

    public override Expression<Func<Product, bool>> GetPredicate()

    {

        return p => p.Name.Contains(query);

    }

}

The beautiful thing in this design is the fact that Specifications are not coupled to the database. They are expressed in terms of the Domain Model and belong to the Domain Model as well. And of course they can be tested against an in-memory implementation of the Repository.

Onion Or Cake?

All the code sits in a single C# project for simplicity, though is layered well.

In classic Domain-Driven Design the Repository abstraction belongs to the Domain layer. I however separate one additional Framework layer, which is a reusable part of the Domain layer across multiple applications and multiple Domains. Both Domain and Framework are kept clear of any infrastructure concerns.

The Infrastructure layer is where all that dirty NHibernate details are hidden. But the IRepository interface and Linq do a very good job to protect the application from NHibernate leaking into the Domain layer.

Here is what NDepend has to say on that matter:

Notice that Unit and Integration tests are separate. Unit tests don’t require any infrastructure to be in place, they can be run against pure Domain code.

What About Transactions?

I intentionally left the Unit Of Work out of the talk. Two reasons for that are the limited time of the talk and some technical problems that I have with the current implementation. So you also won’t find UoW and transactions in this code sample. I’m going to make transaction work in the next version. Stay tuned 😉

Requirements

The code sample is built against the AdventureWorks database. I use NHibernate as an O/R Mapper and Linq to NHibernate for queries. To make NHibernate mappings a bit simpler Fluent NHibernate is used. xUnit.Net is my testing framework of choice.

What About Feedback?

Download the code and tell me what you think.

Written by Sergey Shishkin

03.12.2008 at 14:47

Posted in Development

You Can Make A Change

Tired of "myButton_Click(object sender, EventArgs e)", you can change it to be "OnMyButtonClick(object sender, EventArgs e)". Make Visual Studio conform to the de-facto .NET naming conventions!

Vote for the suggestion on Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=374601

Written by Sergey Shishkin

13.10.2008 at 13:58

Posted in Development

Fluent Interface and Inheritance

While writing the fluent XML writer I got confused about how to make the MemoryXmlWriter class having a really fluent interface. The MemoryXmlWriter inherits all the XML-related methods from the base FluentXmlWriter class and provides additional methods for working with its internal MemoryStream. The problem arises when any base method is called on an inherited instance and an instance of the base class is returned. There is no more way to call methods of the inherited class fluently.

A reasonable workaround for a C# developer would be to use generics to parameterize the type of the instance returned out of the base methods. But I also want to hide generics from clients because all those "<T>" constructs make code to look overcomplicated garbage. And of course, I want both the base class and the inherited class to have a common non-generic base type for polymorphic usage. Let’s look what C# can do about it. I use the foo-bar notation here instead of my XmlWriters for the sake of simplicity:

public interface IFoo
{
    IFoo DoFoo();
}

public abstract class Foo<TThis> : IFoo
    where TThis : Foo<TThis>
{
    public TThis DoFoo()
    {
        Console.WriteLine("Foo");
        return (TThis)this;
    }

    IFoo IFoo.DoFoo()
    {
        return this.DoFoo();
    }
}

public class Foo : Foo<Foo> { }

public class Bar : Foo<Bar>
{
    public Bar DoBar()
    {
        Console.WriteLine("Bar");
        return this;
    }
}

Now one can use the IFoo interface for polymorphism. The concrete Foo class turns out to be extra simple in the sample. In reality it may also have to define some constructors. An instance of the Bar class can be used to get access to the extended functionality and to the IFoo‘s methods at the same time:

IFoo f = new Foo();
f.DoFoo().DoFoo();

Bar b = new Bar();
b.DoFoo().DoBar().DoFoo().DoBar();

From the user’s perspective I like this code, because now the DoFoo() method on the Bar instance returns me back the same instance of the same Bar class instead of its base class or interface. But what was the price of that? Now I got an interface which I did not required, I have to implement the interface explicitly because I also need the same method to return the type parameter. In the end of the day I have one declaration and two implementation to maintain for each single method I want my FluentXmlWriter to have. Also, the implementation is buried inside of the cluttered infrastructure Foo<T> class, making code generation difficult.

But this is in C#. What about VB.NET and its explicit interface mapping? Things remain the same there since the return type of the implementing method must be the same as that of the declaring method.

Let’s try to simplify the previous sample:

public class Foo
{
    public Foo DoFoo()
    {
        Console.WriteLine("Foo");
        return this;
    }
}

public abstract class Foo<TThis> : Foo
    where TThis : Foo<TThis>
{
    public new TThis DoFoo()
    {
        return (TThis)base.DoFoo();
    }
}

public class Bar
    : Foo<Bar>
{
    public Bar DoBar()
    {
        Console.WriteLine("Bar");
        return this;
    }
}

Now I got rid of the IFoo interface and moved the concrete Foo class on top of the class hierarchy. The Foo class became completely unaware of the others. Moreover, the generic abstract Foo<T> class can now be 100% auto generated by a tool. Not bad 🙂

Technorati Tags:

Written by Sergey Shishkin

04.03.2008 at 09:53

Posted in Development