Wednesday, March 7, 2012

Unit of work using lambdas

Are you tired of writing into log file on every begin and end of the method ? Use AOP. Well, not yet ready for post-compiler magic or dynamic runtime proxies ? Let's try lambdas (again).

static void Main(string[] args)
{
    Scope<LoggingFrame>.Wrap(() =>
    {
        Console.WriteLine("Hello world");
    });
}

Would produce this console
2012-03-07 00:46:58,248 DEBUG - BEGIN Main
Hello world
2012-03-07 00:46:58,258 DEBUG - END   Main

How to implement that ?
[DebuggerStepThrough]
public class Scope<TAdvice> where TAdvice : IAdvice, new()
{
    public static void Wrap(Action body)
    {
        IAdvice advice = Activator.CreateInstance<TAdvice>();
        advice.OnEntry(body);
        try
        {
            body();
            advice.OnLeave(body);
        }
        catch (Exception ex)
        {
            advice.OnException(body, ex);
            throw;
        }
        finally
        {
            advice.OnFinally(body);
        }
    }
}
public interface IAdvice
{
    void OnEntry(Delegate body);
    void OnLeave(Delegate body);
    void OnException(Delegate body, Exception exception);
    void OnFinally(Delegate body);
}
Implementation of the LoggingFrame advice is trivial.

Note that you could get similar behavior with IDisposable and using keyword, but you would not be able to log pending exception.
You could also think about TransactionScope, which would call tx.Complete() automatically when no exception is thrown.
Further improvement is to use dependency injection to instantiate the advises.

Another use-case is to implement Unit of Work or session/call context, while using TSL to reach topmost frame. I used it for NHibernate Session and EF DbContext (unit of work) recently. Interesting related article here.

private void Main(string[] args)
{
    Scope<UnitOfWork>.Wrap(session =>
    {
        var people = session.Person
            .Where(person => person.FirstName == "Pavel")
            .ToList();

        NestedLogic(people);

        //DbContext.SaveChanges() will be called here
    });

}

private void NestedLogic(IList<Person> people)
{
    //this will lookup parent session in TSL and reuse it
    Scope<UnitOfWork>.Wrap(session =>
    {
        foreach (var person in people)
        {
            if (person.LastName == "Savara")
            {
                person.Coder = true;
            }
            else
            {
                session.Person.Remove(person);
            }
        }
    });
}

Composition of scopes could be beautified.
Scope<LoggingFrame, TransactionFrame>.Wrap(() =>
{
    throw new Exception("rollback please");
});


[DebuggerStepThrough]
public class Scope<TOuterAdvice, TInnerAdvice> 
  where TOuterAdvice : IAdvice, new() 
  where TInnerAdvice : IAdvice, new()
{
    public static void Wrap(Action body)
    {
        Scope<TOuterAdvice>.Wrap(()=> Scope<TInnerAdvice>.Wrap(body));
    }
}

All code in the article is simplified and real implementation is exercise for readers.

Enjoy :-)

Saturday, December 31, 2011

Fluentator - generate fluent API for your structures

When working with nested structures like configuration or XML it is bit of pain with syntax in C#. Consider this code below. The object initializes in C# 3.0 helped a lot, but it's still pretty far from ideal. Important point here is readability, which is achieved thru nesting the initializers.
var model = new Model();
var pavel = new Employee("Pavel");
model.Companies.Add(new Company("Boldbrick & co.")
{
    Departments = new List<Department>
    {
        new Department("Software & Visions", "swv")
        {
            Teams = new List<Team>
            {
                new Team("Visions")
                {
                    Employees = new List<Employee>
                    {
                        // I was forced to move 
                        // pavel variable declaration completely out of scope
                        pavel,
                        new Employee("Ondra"),
                    },
                    IsAwesome = true,
                },
                new Team("Developers")
                {
                    Employees = new List<Employee>
                    (
                        // I can't do any statements or declarations here
                        // to prepare my data in-place
                        devNames.Select(n=>new Employee(n))
                    )
                    {
                        // note I can't add pavel first
                        pavel,
                    }
                }
            }
        }
    }
});
But there are downsides with approach above. You can't easily add same instance into 2 nodes. It forces you to declare pavel variable completely out of scope. And you can't use statements to prepare your data in place either. Note how Pavel is inserted after other employees into Developers team. The LINQ Select() helped great deal here, but it's not always possible to use it. With more complex model and bigger tree to build, this will become unmanageable mess.

So, extension methods and lambdas to rescue. Do you like code below better ? I certainly do. I can use statements and variable declarations in inner scope. I get more dense and readable code.

var model = new Model();
model.AddCompany("Boldbrick & co.", bb =>
{
    bb.AddDepartment("Software & Visions", "swv", swv =>
    {
        // variable is still bit out of scope, but not in the root scope
        var pavel = new Employee("Pavel");
        swv.AddTeam("Visions", visions =>
        {
            visions.AddEmployee(pavel);
            visions.AddEmployee("Ondra");
            visions.IsAwesome = true;
        });
        swv.AddTeam("Developers", devs => 
        {
            devs.AddEmployee(pavel);
            // I can add more employees after Pavel
            devs.AddEmployees(devNames.Select(n => new Employee(n)), dev=>
            {
                dev.Age = 33;
            });
            // and also can use any complex statement in-place
            for (int i = 0; i < devNames.Count; i++)
            {
                int ix=i;
                devs.AddEmployee(devNames[i], dev =>
                {
                    dev.Age = ix;
                });
            }
        });
    });
);});

How the extension method looks like ?

Below is extension method over external structure Department, which accepts same parameters as Team constructor. Inside is instance creations and adding to the collection. Finally to allow the nesting of scopes, we pass the new instance to Action<> delegate.
static public Team AddTeam(this Department self, string name, Action<Team> result = null)
{
    var item = new Team(name);
    self.Teams.Add(item);
    if (result != null) result(item);
    return item;
}

Generate the extensions

The extension method above is nice and useful but it's quite boring to write it for each combination of container and child item. Multiplied by all constructor signatures. So I decided to create ReflectionFluentator which can generate the code for you. It reads your model via reflection and generates the C# extensions. See sample how to use the generator.

And the same thing for XML ? Sure. You provide the XSD to XsdFluentator. See sample how to use the generator.

var doc=new XDocument();
doc.AddLibrary("Prague",prague =>
{
    prague.AddBook("Saturnin", book =>
    {
        book.AddAuthor("Zdenek Jirotka");
    });
    prague.AddBook("Bylo Nas 5", book =>
    {
        book.AddAuthor("Karel Polacek");
    });
});
This code can generate this XML as expected.
<library id="Prague"
  xmlns="http://polyglottos.googlecode.com/svn/trunk/demomodel/library.xsd">
  <book name="Saturnin">
    <author name="Zdenek Jirotka" />
  </book>
  <book name="Bylo Nas 5">
    <author name="Karel Polacek" />
  </book>
</library>
Note that both generators are more prototypes than ready to ship. They don't handle any edge scenarios when reading the metadata or writing the code. Fluentator is part of Polyglottos project. If you like the idea and wish to contribute improvements, please talk back.

At this point some of you may wonder what else could be made fluent this way. In my case, I realized that I need to generate the code and the code is just nested structure. So I created CodeDom code generator Polyglottos with fluent API. That's for another article next year. Enjoy the party tonight!

Monday, September 19, 2011

jni4net 0.8.6 - release

Changes

  • fixed permission demand for sandboxed environments
  • improved proxygen can't find class reporting
  • improved the way we are looking for jni4net.j-xxx-.jar (while installed in GAC)
  • [#27] - fixed build script problems
Download here

Road map

May people asked for road map. This is my vision, not a promise.

Wednesday, August 17, 2011

jni4net 0.8.5 - release

Changes

  • [# 9] - support for indexer properties [by Johannes Rudolph]
  • [#22] - Potential field name clash due to increasing numbering strategy of field names
  • [#24] - Change of current directory during init may disrupt other code running in parallel
  • [#25] - DirectByteBuffer doesn't work with Java 7
Download here

Monday, July 18, 2011

Host your own Roborumble server

There are several reasons why you might want to run your own Roborumble server. Maybe you would like to run small local contest at your school or workplace. Or maybe you are testing your new shiny robot. Or may you want to collect some battle data, like myself.

The current Roborumble server is created and maintained by Darkcanuck. Luckily he shares the RumbleServer sources via subversion. It is implemented in PHP and MySQL.

Because I'm not PHP+MySQL expert, easiest solution for me was to download ready-made LAMP virtual machine and configure it.
I know you are busy ;-), so I published my virtual appliance, you could just start using it. You can download it and run it in VMWare Player. Password is robocode, you should change it as soon. Or you could follow the guide below.

Configure server

Once you have LAMP stack up and running you need few things:
Install subversion client
Get PHP sources
Configure RumbleServer
Turn on URL rewriting mod in Apache
Configure MySQL database and grant permissions

The appliance has could be configured from web admin. You can access it on https://192.168.1.12/ where 192.168.1.12 is the IP address assigned to the virtual machine by your DHCP server. I will use 192.168.1.12 which was assigned to me in rest of the article.


Webmin->Global configuration
  ->Configure Apache Modules->rewrite: switch ON

MyPhpAdmin
  Create database->roborumble   Import script schema/schema.sql
  Priviledges->add new user->
    name->rumbleuser
    pass->rumblepass
    Database for user->None
    Global privileges->Select+Update+Insert+Delete

On root shell do something like this
apt-get install subversion
cd /var/www/
mkdir rumble
cd rumble
svn co http://darkcanuck.net/svn/rumbleserver/trunk/ .
chmod g+w templates_c/
chown :www-data templates_c/
cat > participants.txt
[paste participants.txt file and press Ctrl-D]
cd config
cp config.php-sample config.php


Participants

Are defined as list of robots and their .jar files. Big competition is driven by this file. We could simplify our own list like this. We host the file on the appliance in folder /var/www/. So create you own shortlist and update it there. Note there are starting and ending tags.
----
<pre>
jk.mega.DrussGT 2.0.4,http://www.minifly.rchomepage.com/robocode/jk.mega.DrussGT_2.0.4.jar
voidious.Diamond 1.5.34b,http://www.dijitari.com/void/robocode/voidious.Diamond_1.5.34b.jar
</pre>
----


Configure client

Download and install Robocode 1.7.3
Edit c:\robocode\roborumble\roborumble.txt

  PARTICIPANTSURL=http://192.168.1.12/participants.txt
  UPDATEBOTSURL=http://192.168.1.12/rumble/RemoveOldParticipant
  RESULTSURL=http://192.168.1.12/rumble/UploadedResults
  RATINGS.URL=http://192.168.1.12/rumble/RatingsFile
  ITERATE=YES

start c:\robocode\roborumble.bat

Purge data

If you need to purge the data from the roborumble database and start from scratch just delete rows using MyPhpAdmin.
delete from battle_results;
delete from game_pairings;
delete from bot_data;
delete from participants;
delete from upload_stats;
delete from upload_users;


Oh, and once you are done with your local competition, don't forget to redirect back to official RoboRumble server and contribute your CPU power!


Download turnkey-roborumble.2011-07-18.zip.torrent

Thursday, July 7, 2011

HowTo: Pass build property from TeamCity into Freemaker email notification template

There is no magic, once you know it. My use-case was to prefix build number with configurable text before sending an email. The text was represented as TeamCity property system.tc.branch.number in my case.

TeamCity email templates are implemented with Freemaker. The TeamCity exposes all build properties as hash table on SBuild.getBuildOwnParameters().

In the template the instance of SBuild is accessible under build variable. Freemaker allows calling bean properties, in our case it would be build.buildOwnParameters, map lookup thru square-bracket syntax [] and literals are enclosed in apostrophes.

#${build.buildOwnParameters['system.tc.branch.number']}.${build.buildNumber}

Tuesday, June 28, 2011

jni4net 0.8.4 - release

Changes

  • Added ability to load proxies into specified classLoader by Jose Chillan.
    Bridge.LoadAndRegisterAssemblyFromClassLoader(File, ClassLoader)
  • JNIEnv.DetachCurrentThread() contributed by Renier B.
  • Bridge.setClrVersion() made static by Leonid Bogdanov
Download here