« Barcelona | Main | P/Invoke limitations »
Mono, .NET and Java
Microsoft recently sponsored a research to compare the development costs of using .NET and J2EE to build enterprise applications. The story is here.
The results are not surprising to me. The study claims that .NET is on aveage 28% cheaper than developing with J2EE-based frameworks. Both J2EE and Swing have been over-engineered and over-designed. It is probably a very solid design, but has abused the model-view-controller architecture. If not kept under adult supervision architects designing MVC platforms make the development of average applications cumbersome.
The results are exactly along the lines of the input we received in March 2003 when we did the Second Mono Survey. Our Survey focused on ASP.NET as a technology for developing web-based applications, and the people we had a chance to interview gave us that same message: ASP.NET saves them on average 20% of their development time.
The research study we did shed some light into the debate. The application serving market can be divided in three groups:
| Market | Development Price Range (dollars) |
Technologies | State |
| Entry level | 0-200,000 | Php, Python, Zope, Perl, home-grown, cgi-bin, asp, aps.net, jsp, j2ee | Plenty of offerings, no dominant player. |
| Mid level | 200,000 to 5,000,000 | J2EE, ASP.NET | J2EE had an early start, but ASP.NET is taking over. These are multi-developer projects of six to twelve months. This market is very sensitive to development times, and a 20% to 28% increase in productivity makes ASP.NET solutions more competitive price-wise and more profitable. The Windows-only nature of ASP.NET its the only thing stopping its mass adoption. |
| High level | 5,000,000+ | J2EE and ASP.NET | J2EE is considered the standard to use. These projects
require hardware mobility and are large
organizational projects. The availability of many J2EE
providers is considered a big plus. The lack of third-party providers for ASP.NET slows down its adoption in this market. |
Mono is by no means ready to be an ASP.NET provider on the high-level application server market today, but the mid-market is the sweet spot for Mono and will help drive the adoption of ASP.NET. This is very compelling, because developers can use the state-of-the-art Visual Studio to create their applications (cutting costs there), and deploy on Linux (cutting costs on the server side).
Plugins in Mono
Nat asked me to write a small document for people who are interesting in creating applications with plugins. The following is the smallest setup I could think of (this is the same model I used on the Dashboard).
Plugins in Mono: (Article Permalink)
The Common Language Infrastructure has various mechanisms that developers can use to extend their applications with plugins. This document describes the facilities available and some possible implementation strategies.
Plugins are dynamically loaded modules that extend the functionality of an application. Plugins can be used to enable developers to extend an application after it has shipped, and also as a modularization technique. Applications like the GIMP use a plugin architecture to implement transformation and file formats.
CLI Foundations
When a program or a library are compiled into assemblies (the binary file format used by the CLI)the information about the available classes, methods, variables, names, parameters are stored into the resulting .exe or .dll. This information can be later retrieved through the Reflection API.
Technically, the only difference between a .exe and a .dll in the CLI world is that executable files contain an entry point, and libraries do not.
For example, the following program will list all of the types available in an assembly. Both a .exe or a .dll will work:
using System;
using System.Reflection;
class ListTypes {
static void Main (string [] args)
{
foreach (string file in args){
Assembly a = Assembly.LoadFrom (file);
Type [] types = a.GetTypes ();
Console.WriteLine ("Assembly: " + file);
foreach (Type t in types)
Console.WriteLine (" Type: " + t.Name);
}
}
}
Compile and run:
$ mcs query.cs Compilation succeeded $ mono query.exe demo.exe Assembly: query.exe Type: Class1 $ _
Once an assembly is loaded, it is also possible to extract the available methods or dynamically invoke methods in the recently loaded assembly. For example, the following program will invoke the method "Boot" on any types passed on the command line.
using System;
using System.Reflection;
class ListTypes {
static void Main (string [] args)
{
foreach (string file in args){
Assembly a = Assembly.LoadFrom (file);
Type [] types = a.GetTypes ();
Console.WriteLine ("Assembly: " + file);
foreach (Type t in types){
MethodInfo boot = t.GetMethod ("Boot");
if (boot == null)
continue;
if (!boot.IsStatic)
continue;
boot.Invoke (null, new Type [0]);
}
}
}
}
We are using the Type's GetMethod to fetch the public method named "Boot". If we find such a method, we invoke it. In this particular example, we want to invoke static methods, so we test for this and we also pass `null' as the first argument to Invoke.
The following sample program can be used to test our new loader:
using System;
public class Demo {
public static void Boot ()
{
Console.WriteLine ("Demo.Boot invoked");
}
}
We compile and run:
$ mcs loader.cs Compilation succeeded $ mcs -target:library demo.cs Compilation succeeded $ mono loader.exe demo.dll Assembly: demo.dll Demo.Boot invoked $ _
Access to the Main Application
It is now possible to load code dynamically, but a plugin-system often will need to access the internal data structures and methods to carry out a more interesting job. Our plugins can invoke easily any methods that is available to thme at compilation time.
The following sample program shows a tiny spreadsheet application which provides support for invoking plugins.
using System;
using System.Reflection;
public class Spreadsheet {
string [,] cells = new string [10, 10];
public string this [int col, int row] {
get {
return cells [col, row];
}
set {
cells [col,row] = value;
}
}
}
public class Driver {
static public Spreadsheet sheet = new Spreadsheet ();
static void Main ()
{
string cmd, r;
do {
Console.Write ("cmd> ");
cmd = Console.ReadLine ();
string [] args = cmd.Split (new char [] {' '});
switch (args [0]){
case "set":
sheet [Byte.Parse (args [1]),
Byte.Parse (args [2])] = args [3];
break;
case "get":
r = sheet [Byte.Parse (args [1]),
Byte.Parse (args [2])];
Console.WriteLine ("value: {0}", r);
break;
case "plugin":
InvokePlugin (args [1]);
break;
}
} while (cmd != "quit");
}
static void InvokePlugin (string plugin)
{
Assembly a = Assembly.LoadFrom (plugin);
foreach (Type t in a.GetTypes ()){
MethodInfo method = t.GetMethod ("SheetPlugin");
if (method != null && method.IsStatic){
method.Invoke (null, new Type [0]);
break;
}
}
}
}
Compile the above like this:
$ mcs sheet.cs Compilation succeeded $ _
Here is the `export.cs' program that we will compile as a plugin:
using System;
public class DumpSheet {
public static void SheetPlugin ()
{
for (int r = 0; r < 10; r++){
for (int c = 0; c < 10; c++)
Console.Write ("{0}, ", Driver.sheet [r, c]);
Console.WriteLine ();
}
}
}
Notice that this plugin needs to access the sheet object in the Driver class from the main program. We will compile this as a library which references the main application. This effectively treats the main application as a library consumed by the plugin.
$ mcs export.cs -r:sheet.exe -target:library Compilation succeeded $ _
A sample session looks like this:
$ mono sheet.exe cmd> set 0 0 hello cmd> set 0 1 world cmd> set 8 8 Eight cmd> plugin export.dll hello, world, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Eight, , , , , , , , , , , , cmd> _
Details
There are plenty of other scenarios and ways of structuring your program to have a plugin system. Currently part of the contract used in this document was to use the public classes, methods and fields exposed by the host application. A common pattern used in plugin systems is to provide a class method to register objects and handlers with the host application.
Gnome 2.4 is out
The anticipated release of Gnome 2.4 is out now. It includes a list of Why use Gnome?
Ars Technica has a pretty good review.
blog comments powered by Disqus




