<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d11473797\x26blogName\x3dDesign+by+Contract\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLUE\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttp://aabsdotnet.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://aabsdotnet.blogspot.com/\x26vt\x3d-2923818330935120734', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>
How to design and build a DBC system using C#, and NVelocity.
Previous Posts

Archives

Links
Design by Contract
Sunday, June 12, 2005

Almost ready to go open source

I have been tweeking and fiddling with the framework in readiness for making it open source. There are still quite a few things I ought to do before making any attempt to publicise it. I thought that since I've been very remiss in not posting to this blog lately I could do some posting. How better than to list what I've got to do before the system is unveiled to the public? I know I'm not exactly going about this in the true open-source way, but I guess I'm a little wary about releasing my code to the public without having crossed as many 't's and dotted as many 'i's as I can find. I'm sure there are plenty of improvements that people will find when I release them, but I don't want any of them to be dumb or outmoded errors! Anyway, enough of such insecurities! Here's what I have to do before D-day:
  • See if I can create a WIX installer that works. Currently I seem to be having problems with adding assemblies to the GAC. My best guess is that WIX is not able to add .NET 2.0 assemblies to the GAC because it's trying to use some sort of reflection on an incompatible assembly.
  • Create a user tutorial. I'll probably do that in this blog. It should be a pretty easy task, since I've gone to great lengths to make the framework as transparent as possible.
  • Document the API using NDoc. As ever, I've been slack in commenting my code. I guess I'll start with the main APIs and then keep at it in the months after release.
  • Run it through FxCop and make sure there are no obvious errors.
  • Run regression tests on the static code generation system! This is potentially of less value than the dynamic code generation system so I have ignored it for a while.
  • Make sure it still compiles on .NET 1.1! And how about Mono? I haven't seen any major commercial projects requiring Mono, but that may change...
  • Make sure that the compilation with NAnt works as well as the VS.NET 2005 beta 2 builds. Especially if WIX is not an option. I need to make tragets that will crerate binary and source distributions for release. This should then be used to upload overnight snapshots to the web each night.
  • Convert the system to work with CruiseControl.NET. I have (so far) had around 5 interviews with ThoughtWorks, so I really ought to be as obsequious as possible to boost my chances with them! ;-)

Once these tasks have been performed, then I ought to post it online and start trying to publicise it a bit more. I can then think a bit more about using the framework in earnest. I want this system because I have an object relation mapping (ORM) system that is just short of being releasable and I would like to augment it with DBC to see whether I can productise it that way. For more information on ORMs, google for Scott Ambler's original postings on a design for a robust persistence layer. I also want to make the second release of the framework self-hosting. That is - I want to use DBC within the DBC framework itself. How much more could I practice what I preach, eh?

May was a quiet month

It's been almost a month since the last time I posted, and I have made a few changes to the DBC framework since then. I'm making changes now in readiness for release to GotDotNet or Sourceforge. So I'm just making sure everything is as logical and consistent as I can make it. Firstly, I have completely rewritten the NVelocity template assembly to simplify it even more (as if that were possible!). Now you can use it like this:
public void TestDefaultCreationOfTemplate()
{
  ITemplate tpl = TemplateManager.CreateTemplate(@"Hello" +
    " ${otherpart}");
  tpl["otherpart"] = "world";
  Assert.AreEqual(tpl.ProcessedOutput, "Hello world",
    "strings didn't match");
}
The observant amongst you will also notice that I'm now using unit test cases from visual studio 2005's unit testing framework - why MS couldn't just use NUnit I don't know (well I do, and it doesn't reflect well on them), especially since their framework seems excessively complicated when using autogenerated tests. Anyway, the template class is now just a very thin veneer over the velocity framework. I am still able, should the need arise, to swap out NVelocity and replace it with something else, but the changeover was mostly involved in recompilation of NVelocity to .NET 2.0 and to add a strong name for deployment to the GAC. I've placed the code generation templates into the Core assembly as resources to allow easier deployment and to make them tamper proof and to get rid of the needless configuration settings to allow the system to find the templates. I've broken out the predicate attributes and the exception types to a separate assembly, so development can be done with DBC attrs even if the DBC system is not in use. It also means the attributes can be put to other uses like documentation or validation. Right now, I'm mostly in performance tweeking and refactoring mode. Here's an example of one of the tests I'm using that shows how the system is to be used now:
[TestMethod]
public void TestTimeToCreateAThousandProxyObjectPairs()
{
  ArrayList al = new ArrayList();
  DbcProxyDynRTCF cf = new DbcProxyDynRTCF();
  int totalToCreate = 10000;
  cf.CreateProxyFor(typeof(TestObjectWithEvents));
  DateTime start = DateTime.Now;
  for (int i = 0; i < totalToCreate; i++)
  {
    al.Add(cf.CreateProxyFor(typeof(TestObjectWithEvents)));
  }
  TimeSpan durn = DateTime.Now - start;
  double d = durn.TotalMilliseconds / ((double)totalToCreate);
  Debug.WriteLine("Average time to create a proxy-object pair" +
    " (ms): " + d.ToString());
  Assert.IsTrue(durn.TotalMilliseconds < ((double)
    totalToCreate) * .17);
}
Currently the average time needed to instantiate a proxy with a target object is around .2 milliseconds. Interestingly it was around 0.16ms with .NET 1.1, but now I'm working with .NET 2.0 the performance is roughly 25% slower. It may be that some of the techniques I am using can be performed in a better way now, but that remains to be seen -- the only deprecated feature that I have not updated is in my use of CreateCompiler to compile the generated code. This piece of code gets called only once, before the timer is turned on. So it couldn't affect the code performance unduly. So where is this much publicised performance boost that we are supposed to get from .NET 2.0?
public CompilerResults GenerateAssembly()
{
  Assert(SourceCollection != null && SourceCollection.
     Count > 0);
  AssertCodeGenParamsAreOK();
  CSharpCodeProvider cscp = new CSharpCodeProvider();
  ICodeCompiler compiler = cscp.CreateCompiler();
  CompilerParameters cp = ConstructCompilerParameters();
  string[] classes = new string[SourceCollection.Count];
  SourceCollection.CopyTo(classes, 0);
  CompilerResults cr = compiler.CompileAssemblyFromSourceBatch
    (cp, classes);

  if (cr.Errors.HasErrors)
  {
    foreach (CompilerError ce in cr.Errors)
    {
      Log(ce.ErrorText);
    }
  }
  return cr;
}

Powered for Blogger by Blogger templates