dinsdag 29 juli 2008

Ignore files in your subversion repository

After reading the pragmatic programmer in my holiday I decided it was time to put theory into practice.  Whenever I perform an check-in in my subversion repository I usually deleted my bin and obj folders manually to make sure they didn't got checked-in.  Of course tortoiseSVN and subversion provides ways to automatically exclude them when you check-in.

So in order to 'avoid my repetitive tasks' and win those crucial couple of seconds on every commit (have you ever count how much this could add-up to on a year basis?) I browsed the tortoise site and found the following documentation:

http://tortoisesvn.net/docs/nightly/TortoiseSVN_en/ch05s11.html#tsvn-DUG-ignore-glob

Here are the settings that I've applied on my projects : */bin */obj */_ReSharper* *.suo *.user *.resharper

image

Right where can I win some more time, maybe I can achieve my 4 hour work week!

maandag 7 juli 2008

Book Reviews: the holiday books

Just returned from my holiday where I had the time to catch up on my reading. I choose a couple of books from my shelf and went on my way to France.

The pragmatic programmer

This book is all about becoming a better and more productive developer.  The book contains tips and tricks to let you focus on the job at hand instead of distracting you from it.  It reads like a novel so it is perfect as holiday lecture (buy this book if you are leaving in the next couple of weeks).

I simply cannot believe that this book is written 10 years ago.  It still is burning accurate and besides the referral to the "upcoming language of java" and "in the future there will be refactorings tools available" you simply cannot tell it is this 'old'. 

I really liked the way the book compared the continuously studying everyone has to do with investing in your stock portfolio, it's all about diversification! 

As a nice extra for one of my colleagues  the books describes nicely the pussy way of development.  :-)

Agile principles, patterns and practices in C#

A must read book for everyone doing agile development in C#.  It starts of with a section explaining what agile development is all about and what are its cornerstones.  The section ends with an hilarious 'role play story on pair programming'. 

The second section is more interesting where all the basic principles of software development pas the revue.  If you don't know what the Single Responsibility  principle, what the open/closed principle has to do when there are no doors involved, when LSP, DIP and ISP are just meaningless acronyms then this book is for you.  The section finishes of with an overview of UML and how to express design in various diagrams.

Section three and four covers the patterns part of the book and it does this by following a case study about a payroll system.  If you have heard of NDepend you will probably be familiar with the principles (REP, CRP, ....) Robert explains when packaging our case study.

I would advice this book to everyone who wants to start with agile development!

I then started to read Implementation patterns from Kent Beck, but the didn't finish it yet.  The swimming pool looked more appealing...

donderdag 12 juni 2008

The pain of development in Vista

I recently bought a new laptop with Windows Vista already pre-installed.  Until that time my development machine was running on XP, but now I had the joy of meeting the latest invention (??) of Microsoft called User Access Control (UAC)!  I am still figuring out if this is supposed to be feature or a bug that the programmers could not fix. 

My problem is the following: Whenever I open a perfectly working solution on my new machine I got an annoying "System.Runtime.InteropServices.COMException" exception hitting me.  I quickly realized it happened only when accessing a Web or Service through IIS.  Whenever you want to access local IIS Website your Visual Studio needs to fired up in the context of an administrator, by default Vista starts applications in a limited-privilege user account.  The solution to this problems is relatively easy, always start your studio in administrator mode.  I created a new shortcut that runs in administrator mode and associated my sln-files to use this shortcut by default.  If you right-click on a shortcut, in the advanced tab you can select the 'run in administrator' option.

Problem solved if you can live with a UAC popup every time you open Visual Studio.  If you anything like me you want to avoid this popup as well :-), my first thought was simply disable the UAC Altogether, but then other features might stop working because windows believes your system is not trustworthy.  Since I usually select proceed in those useless popups I decided to accept this silently without prompting, you can read here how this can be achieved.  I took the liberty of giving you summary here:

Click Start and Control Panel. Switch to Classic View (if you haven't already) and click on the Administration Tools icon. In the list that opens click on Local Security Policy, and in the next window, Local Policies (a tiny bit redundant, but all UIs can't be perfect -- If UAC is running you'll get a UAC pop-up somewhere in here). In the Local Policies list click Security Options, and scroll down to "User Account Control: Behavior" (the full title of the policy is "User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode" but the window barely opens that far). Double-click the title and in the dialog box change its setting from "Prompt for Consent" to "Elevate without prompting." Click OK and the urge to tear your hair and scream at your PC will be greatly diminished in the future.

I hope this post will save you time and headache, till next time.

donderdag 5 juni 2008

NHibernate in Action: Book Review

I finished this 'beta' book today, it took me a while because I have the bad habit of reading multiple books at the same time.  For an NHibernate virgin like myself the book was a very good introduction. It covers everything you need to know to get started with release 1.2.1 version, although nothing is inserted (yet ?? ) for the upcoming 2.0 release.  I hope the final version will include some chapters covering the new features, especially the event/listener model seems to be interesting.  If it doesn't the book might already be outdated upon its release in August.

The thing I was missing was more in depth information about extending the functionality of NHibernate.  We had an issue for instance with the interceptors which you can read all about here, but the book did not provide a lot of information about. 

My overall conclusion is positive because it was a nice intro, but if you already have some experience with NHibernate the book  might be too 'easy' for you.

woensdag 4 juni 2008

Big twitter is watching you.... or me

I finally got the 'stalking decease' as well and subscribed to twitter.  You can follow me here.

zaterdag 31 mei 2008

DDAD: Domain Driven "Allors" Design

As explained in my previous post I am going to build an application to demonstrate what Allors is and how to use it.  I will hopefully have to time to build the same application later on using NHibernate to show both frameworks differences. 

The application I'll be building will take care of the invoicing for a contractor.  It is built using the YAGNI principle (this basically states if you think you need to add complexity to your domain model, you should defer it until the moment you actually need it.  Probably you ain't gonna).  Lets discuss the domain shall we.  The most important class obviously is the Contract signed between a Customer and a contractors's Company.  Both the customer and the company are subclasses of the corporation class, which gives them some common attributes (like Name, Address, Account, .... ).  On the Contract you can then register the hours you worked for them and eventually generate an Invoice for a specific period. 

All relations and classes are shown in the following model:

Version1 
I deliberately kept everything as simple as possible so I can make future improvements to demonstrate what this means in terms of database upgrades, refactorings possibilities, etc....  If you want to follow everything that is explained here below, you can download the complete solution here or built everything yourself of course.

Building the domain (Allors)

To start building an Allors domain you first need to download the binaries and the Allors Repository.  You can either checkout the sources from the subversion (https://www.allors.com/svn/platform) or you can download the Quick Start file I've put together. The zip contains two directories & a command file

  • lib: Directory containing the Allors binaries and the Allors Repository, you should extract these in your solution folder.
  • Allors: Directory for the Allors Domain Files, you should extract these in your domain project folder.
  • AllorsRepository.cmd: file that will startup the AllorsRepository Tool for you domain, this should be extracted in your solution folder.

Step 1: Setting up the solution hierarchy

The solution structure I have applied consists of 4 projects.

  • Diagrams: containing the diagrams of my domain.  This project will contain only generated code with getters/setter that reflect your domain.  You can then use these to generate your class diagrams.
  • Domain: the heart and soul of our accounting application, you should refer to the Allors.Framework.dll here.
  • Population: Helper classes to build your domain objects and setup an initial population for unit/integration testing.
  • Unittests: proving our design and domain is correct and well thought.

image 

Step 2: Creating the Allorized domain

The Allors folder from the zip file needs to be copied into your domain folder.  This folder will contain the meta information (allors.repository) about your domain classes, which is built up using the AllorsRepository-Application (included in the zip file).  if you modify the command file that was included in the zip file so that the parameter passed in to start up the "Allors.Repository.Application.exe" refers to the allors.repository in your domain folder, this file will now fire up the AllorsRepository-Application for your domain.  You should see the following (if you are building from scratch, otherwise your domain will be completely filled in).

image

This screen has three main parts. 

  • The top left has a tree containing all your types and relations in your domain
  • The top right is the property window of the selected treeNode
  • The bottom gives information about errors in your domain

All actions are available by rightclicking the treeNode and then select the action in the context menu or change the node's corresponding properties.  If you need to know how things are getting done, you can checkout the getting started page of the Allors website.  On the bottom you can see that the repository already has one error.  It has no name, so you need to select the domain node and fill in the name in the properties window.

Step 3: Namespaces & Types

Our solution will have two namespaces to start with.  You can see here how you can add namespaces in the repository.  The types we are building are shown in the diagram above, you can easily add them yourself in the allors repository.  It is written out here how you can achieve that.  All objects belong to the Accounting namespace, only the DatePeriod type is more generic and is placed into its own General namespaces

Step 4: Attributes & Relations

We now have domain containing single classes without any attributes or relationships between them.  You cannot call this a domain of course so the logical next step to give our objects data and connect them through the use of relations.  As always you can checkout here how everything can be done.  The above diagram gives you all the information you need to create all the relations.

Step 5: Adding Domain Logic

The Allors domain has been built (you can download the zip file here).  The next step is to generate (right click the domain and select generate) our allors classes, these will be our base classes for our domain objects.  You don't have to remember to inherit any classes or interfaces because we generate a partial class for you as well.  Include these files (located inside the Allors/output/folder by default, but this can be tweaked of course) in your domain project and you can start using them.  Every object you instantiate now is inside a Session, the creation is performed through the Session as you can see in the next code block:

1 public static Account Create(AllorsSession session, 2 string bank, 3 string number) 4 { 5 Check.Argument(number, "number").IsNotNullAndNotEmptyAndNotWhiteSpace(); 6 Check.Argument(bank, "bank").IsNotNullAndNotEmptyAndNotWhiteSpace(); 7 8 var account = session.Create<Account>(); 9 account.Bank = bank; 10 account.Number = number; 11 12 return account; 13 }

Adding the actual business logic is done simply by adding the methods into your class (as you normally would)

1 public TimeRegistration RegisterWorkingTime(DateTime date, Double hours) 2 { 3 return TimeRegistration.Create(AllorsSession, date, this, hours); 4 } 5 6 public Invoice BuildInvoice(DatePeriod period, 7 String reference, 8 DateTime invoiceDate, 9 IInvoiceCalculator invoiceCalculator) 10 { 11 VerifyThatInvoiceReferenceIsUnique(reference); 12 13 var timeRegistrations = new TimeRegistrationFinder(AllorsSession) 14 .GetNotInvoicedTimeRegistrationsFor(this,period); 15 if (timeRegistrations.Length == 0) 16 { 17 throw new ArgumentException("Invoice must contain TimeRegistrations"); 18 } 19 20 var invoice = Invoice.Create(AllorsSession, reference, invoiceDate); 21 AddInvoice(invoice); 22 23 foreach (var timeRegistration in timeRegistrations) 24 { 25 invoice.InvoiceTimeRegistration(timeRegistration, invoiceCalculator); 26 } 27 28 return invoice; 29 }

Step 6: Unit Testing

Since all objects are Session aware we need to have a Session in our UnitTests.  For performance reasons we will not use a real database, but rather work completely in memory.  The following code creates an in-memory session for our domain. 

var population = new Allors.Adapters.Memory.AllorsConnectedMemoryPopulation(new AccountingDomainConfiguration()); population.Init(); _session = population.CreateSession();

You can then create your objects with this sessions and perform the regular tests you would normally write.

1 [TestFixture] 2 public class When_creating_an_account : AllorsBaseTest 3 { 4 private AccountBuilder _builder; 5 6 [Test] 7 [ExpectedException(typeof(ArgumentNullException))] 8 public void Then_expect_an_error_when_the_number_is_null() 9 { 10 _builder = new AccountBuilder(Session); 11 _builder.WithBank(null).Build(); 12 } 13 }

The final step is to make our domain persistent.

For this I created a new project (IntegrationTests).  You do not need to supply mapping files because Allors will make and initialize the database scheme for you based on the meta information you supplied.  This is achieved by simply instantiating the correct population and Session, here we will use the SQL Server Express Edition.  For unittesting we created the population in code (and for memory), you could as well set everything in the config file:

  • First of all you need to declare the allors section in the config
  • You need to configure your populations(or multiple of them) + connectionstrings
  • Finally you need to create the population from based on the name in the config
1 <configSections> 2 <section name="allors" type="Allors.AllorsConfigurationSection, Allors.Framework"/> 3 </configSections> 4 5 <allors> 6 <populations> 7 <add name="AccountingPopulation" 8 type="Allors.Adapters.SqlClient.AllorsSqlClientPopulation, Allors.Adapters.SqlClient" 9 domainConfiguration="AllorsDomains.AccountingDomainConfiguration, Pdbc.Accounting.Domain" 10 connectionStringName="accounting"> 11 </add> 12 </populations> 13 </allors> 14 15 <connectionStrings> 16 <add name="accounting" connectionString="Data Source=Pdbc-Laptop\SqlExpress;Initial Catalog=accounting;Integrated Security=True"/> 17 </connectionStrings>

Then in code we can retrieve the population and instantiate the session.  The Init method by the way drops the database and recreates it which makes sure that our integration tests always have the latest version of the database scheme available.

1 var population = AllorsConfiguration.GetPopulation("AccountingPopulation"); 2 population.Init(); 3 _session = population.CreateSession();

Check the complete sample along with the unittests for a complete overview.  As you notice, the major difference with traditional POCO domain objects is that we need to inherit from an Allors Class.  This Class encapsulates the access to a strategy object which contains all your class attributes and object relations.  This way we can keep all objects managed by Allors which has a lot of benefits (lazy loading, managed relations, ...) , but that is for a next post. 

Let me know what you think about it and have a spin with the sample.  

dinsdag 27 mei 2008

Filtering your Nhibernate SQL Log: The good way

Apparently my previous post about filtering out the unique sql statements NHibernate fires at your database is a quick and dirty hack.  Sure it works but why create a complete new appender  if all you want to do is decorate the existing ones with filtering.  If I would have read the documentation that the good people of log4net have prepared for the world, I would have noticed the concept of Filters.  These form a chain that the logging event has to pass through in order to actually get logged.

Here is the same code that should do the trick using the filters, remember to add this filter in your appender declaration in the configuration file

public class NHibernateUniqueQueryFilter : FilterSkeleton { private static readonly List<String> statements = new List<string>(); public override FilterDecision Decide(LoggingEvent loggingEvent) { var message = loggingEvent.RenderedMessage; var index = loggingEvent.RenderedMessage.IndexOf(";"); if (index != -1) { message = loggingEvent.RenderedMessage.Substring(0, index); } if (statements.Contains(message)) { return FilterDecision.Deny; } statements.Add(message); return FilterDecision.Accept; } }