Tripping over logs: A story of Unity - Part 1
Welcome to the first part in my series on using Unity, which is a Dependency Injection or Inversion of Control tool/framework/thing from the p&p group. It’s a big and (over) complicated topic so if what I have just said means nothing, fear not for it will all make sense soon. I have broken this into a series to make it easier to digest. What I am going to do is look at a practical approach to using Unity, I will not be going into DI or IoC those topics as people smarter than me have done a much better job (part 6 has links). If you want the theory look somewhere else, if you want to get running with Unity this is for you.
This is a multi-part series as such here is the series guide in case you are looking for the rest of the series:
- Part 1 - Introduction to the problem
- Part 2 - Changing the code to use basic unity functions
- Part 3 - Life time management
- Part 4 - Changing the code to use interception
- Part 5 - Interception supplementary
- Part 6 - Wrap up
The Problem
A few years back I was developing an enterprise solution for a bank which integrated MSCRM into a number of systems, and so I needed to make sure I did logging (that’s what enterprise apps have, right?). Initially I had a simple “write to text file” logging system, which worked fine on my machine (if you can see what the problem is in that sentence you been developing too long). That is until we started testing and we ramped up the usage and I hit concurrency and locking issues. That prompted me to rip out all the logging and use the logging within System.Diagnostics.Trace as it seemed like it would work better, and it did for a long time. At some point I was pulled back to project (I left it for a long time) and needed to change the logging to use the p&p Enterprise Library logging. It was only at this point did I stop calling the System.Diagnostics.Trace code directly in each place for logging and start calling a custom method. This is what it sort of looked liked, excepted I had lots more parameters on the logging (level of message, source component etc…) and we logged every time something changed not just entry and exit:
public void DoSomething()
{
LogThis("Do Something Start");
...
LogThis("Do Something End");
}
When I changed it out I did some number crunching and realised that 40% of all the lines of code was these calls to logging! I remember thinking that was well done and how proud I was of my logging skills. Now days I look back at that as ridiculous. Not the fact I did logging, just how much code was spent on it and how tightly bound it was. So how could I do it better now days, well through a principal called Dependency Injection and an implementation of it called Unity (from the p&p team in their Enterprise Library).
Note: I am using the example of logging as the problem to solve, but really DI can be used for anything.
I must admit that Unity though is anything but simple, it is one of the hardest things I have had to learn in a while. What made it tough was understanding the documentation which enables you to learn Unity, but you need to understand Unity first to understand the documentation, talk about catch 22. It’s odd because the other blocks in EntLib are easy to get up and running but with Unity the samples are confusing and the help more so. In the end, some search kung fu + luck + patience seems to be what is needed to get through it. That said I feel a simple series of blog posts may help others out, which is what this is ;)
Starting Block
A special note is that this series is HEAVY with code and makes the articles look long, but actually I am repeating the code each time so you can compare the changes easily.
So lets start with a simple application as our base which will make it clear what we have and what we will change to get Unity working. As those who attend any of my sessions know I love console apps so I’ve whipped up a simple on that writes to the screen. The code looks like this:
using System;
namespace BigSystem
{
class Program
{
static void DoSomething(string Username)
{
Console.WriteLine("Hello {0}", Username);
}
static void Main(string[] args)
{
DoSomething("Robert");
Console.ReadKey();
}
}
}
And the solution like this (note the references - super clean):
Now using my “Enterprise Skills” from earlier, we add some logging like so:
static void LogThis(string Message)
{
System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
}
static void DoSomething(string Username)
{
LogThis("DoSomething Called with Username Parameter set to:" + Username);
Console.WriteLine("Hello {0}", Username);
LogThis("DoSomething Completed");
}
static void Main(string[] args)
{
LogThis("Application started");
DoSomething("Robert");
Console.ReadKey();
LogThis("Application Completed");
}
Right, so that code is not bad. It works which makes the (imaginary) customer is happy. This code is not good either, because if we want to change anything it’s a big issue, likely “solved” by a find and replace. A better route would be to take the logging out and define it in a separate class that inherits from an interface. This means when we create the class we can change that one place and all the code is effected. So that would look like this:
class Program
{
static ILogger logger = new DebugLogger();
static void DoSomething(string Username)
{
logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
Console.WriteLine("Hello {0}", Username);
logger.LogThis("DoSomething Completed");
}
static void Main(string[] args)
{
logger.LogThis("Application started");
DoSomething("Robert");
Console.ReadKey();
logger.LogThis("Application Completed");
}
}
public interface ILogger
{
void LogThis(string Message);
}
public class DebugLogger : ILogger
{
public void LogThis(string Message)
{
System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
}
}
Note the constructor for logger and the interface and class below. The reason this is powerful is if I wanted to change this to output to the console I could spin up a new class, and just change the constructor for logger, as in below:
class Program
{
static ILogger logger = new ConsoleLogger();
static void DoSomething(string Username)
{
logger.LogThis("DoSomething Called with Username Parameter set to:" + Username);
Console.WriteLine("Hello {0}", Username);
logger.LogThis("DoSomething Completed");
}
static void Main(string[] args)
{
logger.LogThis("Application started");
DoSomething("Robert");
Console.ReadKey();
logger.LogThis("Application Completed");
}
}
public interface ILogger
{
void LogThis(string Message);
}
public class DebugLogger : ILogger
{
public void LogThis(string Message)
{
System.Diagnostics.Debug.WriteLine(String.Format("{0}: {1}", DateTime.Now, Message));
}
}
public class ConsoleLogger : ILogger
{
public void LogThis(string Message)
{
Console.WriteLine("{0}: {1}", DateTime.Now, Message);
}
}
This is great, except to change the type of logger I need to change the code. Wouldn’t it be better to
- Be able to specify in a configuration file what should be used?
- Instead of instantiating a logger (like with the constructor), I could have a bag where code could reach into and ask for a logger?
This is what Unity provides at a basic level and we will implement in the next post, but trust me it goes much further and becomes much more powerful.
Search better
Something I have always thought of as a secret weapon in my skills is that search the Google has generally yielded good results or I find I am alone in my problem. I have found that others do not do this as well, often times they search - get nothing, come to me for help, I search and get what they need. Regardless there is a interesting game from MS research which shows you a page and you search for it (backwards to the norm) and score points for how high it appeared in the rank and if you didn’t use common phrases.
My gripe with it is that it has a timer (how many can you do in set time) and since it needs to load the pages, us poor South Africans with no bandwidth it makes the game go slower. I figure I could get 4 or 5 more pages in with decent bandwidth. Oh well, check out PageHunt
Thanks to Alfred for the heads up.
S.A. Architect Community Website Stats - December 2008
Since I took over the operations side of the S.A. Architect site I have kept stats on how well it is doing. The stats are based off of IIS log parsing as well as off of the stats information from SharePoint (which powers it). I have decided to share these each month with the community.
Some notes on it:
- Distinct Users means people which can be identified through logs/tracking to be unique (it’s not an exacting science so there may be people who are counted more than once while others are grouped together as they come from behind a proxy). They are not members and can include things like search bots. I don’t care about the number too much on this but rather the trend.
- Registered Members are people who have completed the registration form on the website.
You can definitely see that people are on holiday over December as the number of requests/users etc… have all dropped, we did however gain 4 new members in the last month!
Mac & IPhone Developers Wanted
Rein is organizing the first CocoaHeads meeting in Africa. If you are interested in development on Mac OSX or IPhone then you have to see http://www.noggin.co.za/2008/12/cocoaheads-johannesburg/
What is a CocoaHead
CocoaHeads is a group devoted to discussion of Apple Computer's Cocoa Framework for programming on MacOS X. During monthly meetings, members present on their projects and offer tutorials on various programming topics.
It’s at the BB&D offices, so I may decide to pop in myself and ask questions like “how does this compare with .Net or Java frameworks?” and “why should I bother when I have Mono/Silverlight/Flash/Air/Java etc…?”, which I am sure will lead to me being beaten by a Mac developer ;)
Installing MSMQ in Domain Mode on Windows Server 2008
Yesterday I needed to install MSMQ on my laptop which runs Windows Server 2008, which wasn’t as logical as it first appeared. I simply fired up the Server Manager tool, went to features, selected Message Queuing and clicked next. However my code kept giving me an error: “This operation is not supported for Message Queuing installed in workgroup mode.”
So I went to find out what this mean, and it turns out MSMQ has two modes workgroup and domain. Domain is the “yes you can” mode where everything works while workgroup has restrictions:
The following restrictions exist when using Message Queuing in workgroup mode:
- Computers in workgroup mode require direct connectivity with a destination computer, and only support direct message transmission. Messages sent by such computers cannot be routed.
- There is no access to Active Directory Domain Services. As such, you can create and manage private queues only on a local computer. You can view the list of private queues on another computer, and the messages in them, using the Computer Management snap-in. For information about managing queues on remote computers, see Verwalten von Warteschlangen auf anderen Computern. You cannot view or manage public queues or any other information in Active Directory Domain Services. You can, however, send messages to or retrieve messages from private queues if there is direct connectivity.
- Internal certificates cannot be used for sending authenticated messages; an external certificate must be used. For more information about user certificates, see User Certificates.
- Messages cannot be encrypted. For more information about encryption, see Encryption for Message Queuing.
- There is no support for dependent clients. For more information about restrictions on the deployment of dependent clients, see Dependent Clients.
- Cross-platform messaging is not supported. For more information, see Cross-Platform Messaging.
That is taken from the helpful TechNet page Deploying in Workgroup Mode, which also states:
The default installation setting is that the directory service Integration feature is installed
Oddly enough though that is NOT what I got, in fact when I went to check Directory Service Integration had not been installed even though I am on a domain (and was connected to the network at the time)! To fix it, I had to go back to the Server Manager Tool, Features, Message Queuing and manually select it.
TFS Branching Guidance is Out
Very late notice from me (been sitting in my inbox for 2 weeks) but the TFS branching guidance is now out on CodePlex: http://dotnet.org.za/willy/archive/2008/12/20/vsts-branching-guidance-ii-a-great-guidance-release.aspx
Interesting it’s the 25th highest download on CodePlex at the moment too! Guess it shows that it isn’t just me and Ryan spending a lot of time trying to figure out the perfect strategy!
.NET 3.5 SP 1 GDR is Out
The .NET 3.5 SP 1 GDR (General Distribution Release), basically the patch for the bugs in .NET 3.5 SP 1, is now out! Details of the patch are/will be available at KB959209
Father Christmas is a SharePoint fan
It really is the season of giving, especially for the SharePoint developers/users/fanboys (yes Marc, I am looking at you). Some of the presents that are under the tree are:
WSRP Toolkit for SharePoint: http://feeds.feedburner.com/~r/sharepointteamblog/~3/485910608/announcing-the-wsrp-toolkit-for-sharepoint.aspx
The WSRP Toolkit for SharePoint provides sample code for producing WSRP conformant data from SharePoint lists and libraries. External portal platforms (e.g. BEA AquaLogic Portal, IBM WebSphere Portal, SAP NetWeaver Enterprise Portal etc.) can then render SharePoint data natively through their WSRP consumer portlets.
I am excited about this because it really does being more interop to SharePoint.
The SharePoint Guidance from the patterns & practices team: http://blogs.msdn.com/francischeung/archive/2008/12/18/shipped-sharepoint-guidance.aspx
- Architectural decisions about patterns, feature factoring, and packaging.
- Design tradeoffs for common decisions many developers encounter, such as when to use SharePoint lists or a database to store information.
- Implementation examples that are demonstrated in the Training Management application and in the QuickStarts.
- How to design for testability, create unit tests, and run continuous integration.
- How to set up different environments including the development, build, test, staging, and production environments.
- How to manage the application life cycle through development, test, deployment, and upgrading.
- Team-based intranet application development.
I have underlined the one that most excites me, unit testing SharePoint!
SharePoint User Interface Extender: http://blogs.msdn.com/chrisfie/archive/2008/12/19/announcing-the-codeplex-release-of-shuie-sharepoint-user-interface-extender.aspx
ShUIE is an addition to Microsoft SharePoint that allows a developer to inject JavaScript and CSS fragments depending on the context of the page being displayed. JavaScript and CSS injected can be optionally minified, and jQuery is included to increase functionality.
This will just make things like Slide.Show integration or jQuery integration so much easier!
SharePoint on the iPhone: http://blogs.msdn.com/ekraus/archive/2008/12/18/sharepoint-on-the-iphone.aspx
-Asynchronous – even with poor reception, the browsing experience should be “good”
-Available via iTunes App Store
-Advanced compression algorithm – faster downloads & browsing
-Uses SSL to connect
So all you buggers who went to CT for a holiday, us who remained now have something to keep us busy and give us an edge over you for next year.
The Cat(.NET) is out of the bag
Those who know me as a developer, and those who attended the boot camp I ran for the last two weeks, have an idea that I like analysis tools (in the boot camp I present a session on my favorite 7 tools, 3 of them are analysis tools). That said I have been following a team at Microsoft for ages who have been building a tool called CAT.NET, which is another static analysis tool. This one focuses on analyzing code for security issues. I looks good, but it really doesn’t blow me away.
What’s the first thing you do when you get a new tool? Run it against your own code and then the Microsoft code ;) No where could I get this code to ever give me a security issue – which is either a good or bad thing. When it’s done it provides a report in HTML and XML which is boring as hell:
The report on System.Web.Services.dll
To see a problem I looked at the rules, which are defined in XML, to actually force an issue. I decided to take a stab at the process command execution rule, with the amazingly complex code like this:
This produced a nice report like this:
That said during one of my tests with it I did get a different result, a nice crash when checking System.Data.dll
StackOverflowException in the security application.
But none of the above is the reason why it does not blow me away, it doesn’t blow me away because it’s another tool that is actually not needed. Looking at the files and code (thanks to reflector) this could have easily been built into FXCop and made that a better solution overall. It is in beta still, so hopefully this is an indication of a tool that has been grown in the dark and now that the light of the public the team will start to understand real world scenarios.
If you needed an indication of the beta status of this tool, check out how many NotImplementedExceptions are in the code still :(
Remote only means in America
Oh well, no freebies for me. It seems the SharePoint REMOTE survey I mentioned is only for American’s. I am seriously wondering if they know how remote South Africa is compared to Redmond… maybe they thought I was in the other Johannesburg.