Amptools.Net

simplify your life.

c#

The trouble with porting migrations and railties into other languages.

No Gravatar

I’ve been toying with API design for solid and simple with Ado.Net to build migrations on top of and possibly layer for building ORMs on. Ironically, Rob Conery, of Subsonic fame, just posted a page (or blog) about migrations in .net and subsonic in general.

The Problem(s).

Database agnostic scripting in C# and PHP and executing sql statements without having to use a heavy ORM in C#.

Obviously, Rails makes a good run at these problems with active record’s built in migrations that everyone and their mother (or at least their co-workers) tries to mimic.   However C#, PHP, and other C style languages lack that Ruby Meta Programming magic.

So why not just include active record into a project that isn’t rails?  This might be doable with Iron Ruby’s release on the horizon. Unfortunately the cost of adding another language to a project is not always justifiable (as some rubyist zealots tend to forget ;) .

So why not just port the awesome library?

After much time over the last year or so, I’ve come to the conclusion that porting libraries from other languages often comes with delusions of grandeur.  Especially when the languages differ on key features.

Ruby and in some ways Javascript, have a much better mechanism for the portability and mixing in methods. Ruby itself has the ability to create powerful readable Domain Specific Languages that other modern languages will not be able to copy.

You tend to see possible extra noise or reduced flexibility when you compare something like Migrator.Net

[Migration(20080805151231)]
public class AddCustomerTable : Migration
{
    public override void Up()
    {
         Database.AddTable("Customer",
             new Column("name", DbType.String, 50),
             new Column("address", DbType.String, 100),
             new Column("age", DbType.Int32)
        );
    }

    public override void Down()
    {
        Database.RemoveTable("Customer");
    }
}

to Rails Migrations.

class 20080805151231_AddCustomerTable > ActiveRecord::Migration
  def self.up
    create_table :customer do |t|
        t.string   :name,     :limit => 50
        t.string   :address,  :limit => 100
        t.integer  :age
   end
 end 

  def self.down
    drop_table :customer
  end
end

The biggest issue I see though is sometimes throwing out the baby with the bathwater by not using some of the same naming conventions because the languages do differ.

Possible Solutions Or Ideas

At least when it comes to C# 4.0 it shouldn’t be too hard to create a .Net library and then create a thin DSL layer in Ruby through Iron Ruby to make calls to the .Net lib.  That coupled with some form of code generation could give you a decent programing work flow.

Another option is to port key features from Rails, adapt to the language that your working in, but at least keep some kind of consistency in naming.

Or you could do a hybrid. That way you have the ability to create a readable DSL in projects that can allow for this or let you fall back to your native language if it doesn’t.

It is still ugly and verbose, but at least it follows in some proximity to its ported counter part.

[Version(20080805151231)]
public class AddCustomerTable : Migration
{
  public override void Up()
  {
    CreateTable("Customer", (t) => {
      t.String   ("name",     (c) => { c.Limit = 50; });
      t.String   ("address",  (c) => { c.Limit = 100; });
      t.Integer  ("age");
    });
 }

 public override void Down()
 {
    DropTable("Customer");
 }
}

And it shouldn’t be hard to build on an underlying API. If done right, you could use the DLR for Ruby or even Python for scripting access or creating that thin readable DSL layer.

It would have probably been cleaner to use optional parameters, but ‘default’ and ‘null’ are keywords in C# and adding @ to keywords for variables can distract from readability.

Another path is to create something new that adapts to your language but does the same thing in principle similar to what Rob partly did for Subsonic 3.0’s migrations.  Porting could be trying to put a square peg in a round hole. So its time to create that peg that fits.

I’ll have some follow up posts that cover ideas on the other areas of being able to script sql in C# with Ado.Net as well as experimental APIs and concepts.  If you got any comments, leave em.

Tags: , , , , , ,

Switching between Ioc libraries in Net.

No Gravatar

Lets face it. Some developers are religiously attached to their beloved languages, frameworks, and libraries.

This becomes a problem when building software with hopes of gaining a developer base. If it is not built on Unity, Castle Windsor, Structure Map or [insert beloved Ioc library here], they refuse to work/use the software.

Evidently others have had this issue and have created a solution, the common service locator.  I ran across while searching for asp.net  mvc and DI (dependency injection) for models. More on DI with models inside controllers in a future post.

How to use

Download the library from codeplex.com/CommonServiceLocator

Its pretty straight forward.  Download the service locator adapter for the Ioc library of your code on the codeplex.com/CommonServiceLocator

choose the adapter for your Ioc library.

choose the adapter for your Ioc library.

Configure your Ioc library in the usual manner. Then pass the container into the adapter.

        private IServiceLocator CreateLocator()
        {
            var container = new UnityContainer();
            container.RegisterType<IUser, User>();
            container.RegisterType<IMembership, Membership>();
            container.RegisterType<IUser, Loser>("loser");

            return new UnityServiceLocatorAdapter(container);
        }

Then tell the service locator which adapter you are using.

        private void SetupService()
        {
            // CreateLocator returns IServiceLocator in the above method.
            ServiceLocator.SetLocatorProvider(() => CreateLocator());
        }

Then use the locator to return the adapter, which will allow you to use a common interface to resolve your dependencies.

        [It, Should("resolve the type to the default")]
        public void ResolveType()
        {
            this.SetupService();
                         // gets the current adapter for the Ioc Library.
            var resolver = ServiceLocator.Current;             

            // resolves the type.
            var result = resolver.GetInstance(typeof(IUser));

            // verify the result is the right type for the contract.
            result.IsInstanceOf(typeof(User));

            // this user should not have a membership.
            var user = (User)result;
            user.Membership.ShouldBeNull();
        }

Some Caveats.

Someone named the base service locator class in a java like manner using Impl.

The assemblies for the Unity Ioc are not strong named assemblies. I had to create a key, sign the assign the assemblies for Unity. You can download the midori-project which has the signed assemblies for Unity under the vendor folder.

Further Usage and Reading

If you would like to check out the spec and see how it might be used, check out the spec in the midori core. This will give you some context.

You can also read more about it on codebetter.com as well as the initial post from Jeremy Miller that spawned someone to write this.

Tags: , , , , , , ,

PHP lacks true object comparability

No Gravatar

For those of you who read the f* manual and see that section called object-comparison. You already realize that its a misnomer or you might be oblivious to another reason why objects in PHP are still second, even third class citizens.

Currently I’m writing a moderate set of Types for (granted i have most of it already written, i’m going back and for the first ctp just releasing the core types, which means i need to document, test, and test some mo). And for those of you that think this is a crazy idea, welp the PHP internals have started to do the same things themselves…. just lacking documentation and anything really useful at the moment. This just adds to why PHP feels like the IE of programming languages and a complete blight.

I think its sad that PHP 5.3 is currently at RC2 as I write this post and the only thing you can really check with object is equality using ==. You can not use operators like greater than (>), less than(<), etc on objects in PHP. The code below will illustrate php’s lack of true object comparison. Though I won’t say this takes away from the whole notion that PHP is enterprise ready, it does take away from the ease of use of objects in PHP and thus could take away from its maintainability.

class Midori_Int32
{
    public $value = 0;

    public function __construct($value = 0)
    {
          $this->$value = $value;
    }
}

 $a = new Midori_Int32(45);
 $b = new Midori_Int32(10);
 //this would be legal, for shallow checking use ==, use === for deep comparisons
 $condition = ($a== $b)
// this is illegal in php
$condition2 = ($a >= $b);

In Ruby (where everything is an object) they allow for operator overloading on method so you can define custom object types with comparability.

class MidoriInt32

  def initialize(value)
       @value = value
  end

  def === (obj)
    return @value === obj
  end

  def > (obj)
    return @value > obj
  end
end

a = MidoriInt32.new(3)
b = MidoriInt32.new(4)

condition = (a === b)
condition = (a > b)

though it may be unknown, you can do the same in dot .net using . If you need to override things like math operators or type conversion you need to check out the wicked cool

using System;

public class MidoriInt32 : IComparable
{

     public MidoriInt32(int value)
     {
         this.Value = value;
     }

     public int Value { get; set; }

     public static MidoriInt32 operator +(MidoriInt32 objA, int objB)
     {
          return new MidoriInt32(objA.Value + objB);
     }

     public static MidoriInt32 operator +(MidoriInt32 objA, MidoriInt32 objB)
     {
          return new MidoriInt32(objA.Value + objB.Value);
     }

     public int CompareTo(object obj) {
     {
          if(obj is int)
                return this.Value.CompareTo(obj);
          else
                 throw new ArgumentException("Object is not an integer");
     }
}

// test
class TestStuff
{
     public void Test()
     {
           var a = new MidoriInt32(3);
           var b = new MidoriInt32(4);
           var condition = (a > b);
           var condition2 = (a === b);
      }
}

Tags: , , , ,