tsJensen

A quest for software excellence...

DomainAspects 2.0: Aspect Oriented Library with Generic WCF Host

Would you like to just focus on your business domain and host it anywhere easily rather than fussing with infrastructure? With DomainAspects you just write the interface in a project called [MyDomain].Common and the implementation is a project called [MyDomain]. Now add a brief and easy configuration string to both client and service host and xcopy deploy. Restart your hosting service if you are using the domain remotely.

With DomainAspects, all access to the implementation is now controlled as you have specified through easy attributes on your implementation without ever writing specific code to validate and authorize. Each and every call is logged without adding any logging code. Each and every exception is logged without ever adding a try/catch block in your code. And exceptions are captured, logged, and thrown up the chain to the client.

Introducing the 2.0 version of DomainAspects. This new version contains some major changes, the chief among them is the introduction of a WCF host container that allows you to access your aspect oriented domain layer remotely. More on the changes and features later, but first, let’s review what has come before and contributed to this new release:

And some earlier posts that have formed the creation of the WCF host in this new version:

DomainAspects 2.0 Introduced Today

Over the last couple of months, I’ve spend considerable time on the weekends to complete the idea of merging my previous work on a generic WCF host into my DomainAspects project. Since I had not touched either of these projects for some time, it was fun and interesting to look at them from a new perspective. There are many changes for the better here. Please download it and give it a try. I am eager to hear your feedback.

New in DomainAspects 2.0

Today, I’m releasing DomainAspects 2.0 which supports the following new features:

  • A WCF host service for accessing domain services running in another process or server with the following features/benefits:
    • Fast and encrypted net.tcp binding with Windows permissions.
    • Simplified custom configuration section that is the same on client and server.
    • Custom instance provider uses the DomainAspects service factory and Windsor for instance creation and release.
    • Ability to specify service instance lifestyle closely matching Windsor (PerThread, Pooled, Singelton, SingleCall).
    • Service host that will run in console mode for easy debugging.
    • Flip a config switch and install the service host as a windows service. No recompile required.
    • RemoteClient implements IDisposable correctly, dealing with Abort vs Close for you.
    • Host can be configured to use a fake PrincipalProvider for easily testing a variety of user roles and combinations.
    • Reliance on DomainAspects for authorization rather than configured local Windows groups.
  • A light remote client assembly allows access DomainAspects with minimal deployment requirements.
  • Local client and remote client both return an instance of the service interface, allowing a domain to be moved to another process or remote server with minimal changes to client code.
  • Upgrade to the current stable release Castle Windsor 3.0 container libraries.
  • Improved domain service factory allows greater instance creation control.
  • Additional tests, including multi-threaded remote tests focusing on instance creation and pooling.
  • More intuitive, self-describing classes to make understanding the code easier.

Using DomainAspects 2.0

Using the DomainAspects solution is easy. You must have Visual Studio 2010 Pro or higher. If you do not, you may spend considerable time trying to get it running. I would not recommend it.

Download the code and make sure you right click the zip file and go to properties and unlock the zip file before you extract it.

To run remote tests, be sure to start the DomainAspects.Host without debugging first. I recommend running the MultiRemoteTests class using a multiple project startup with the host running first and the DomainAspects.TestConsole running the test rather than the automated tests runner since I have not found a way to get those tests to run properly within the test harness.

Now run the tests. Watch the host console as the MultiRemoteTests run. Note the instance creation on second and third run take zero time because these instances have been pooled.

When you are ready to build your own domain service, just follow the examples in the TestDomain and TestDomain.Common projects. Configure the host and the client as shown in the app.config files in the included projects appropriately to match your new domain and domain.Common assemblies.

If you are going remote, build and deploy the DomainAspects.Host. Make sure you switch the “consoleMode” attribute in the config on the server side to “Off” so that it will install and run as a service.

Download DomainAspects20.zip (2.10 mb)

Facebook Sucks Away Too Much Time

I have removed Facebook mobile apps from my mobile devices. It was really just occupying too much of my time. I am now considering removing my account entirely. I am finding less and less value in the increasing amount of time I spend on the site. what about you? Have you abandoned Facebook too. Let me know why and how leaving Facebook has affected your life.

Choosing a Content Management System

Growth in the content management system (CMS) market is strong as more and more companies look for software to help them manage their burgeoning coffers of content. This growth is partly fed by the growing temptation to use these systems for purposes far beyond managing content with CMS vendors tacking on every new feature they can dream up to feed this frenzy. The result is often a bloated, unwieldy, unmanageable, complexity induced bug-infested mess.

I have a relatively high level of interest in this space given my brief professional experience in this market. So I read with interest a post today on the subject by one of my favorite software development authors, Martin Fowler. In his post entitled Editing Publishing Separation Fowler discusses the advantages of separating the editing data and experience from the publishing experience and published data. I invite you to read his article as he makes a very cogent argument which should be taken into account as you consider choosing a CMS.

Before he makes this point, he sets up his theme with this preamble:

"...a regular theme has been the growing impact of content management systems (CMS). They aren't usually seen as helpful, indeed there is a clear sign that they are becoming a worryingly invasive tool - used for more than their core purpose in such a manner that they hinder overall development."

It is precisely this thought which accurately represents my own limited experience in the CMS market. So here are my recommendations for consideration when choosing a CMS for your content management purposes.

  • As Martin suggests, look for a separate editing and publishing experience including separation of data and the advantages that can come from that.
  • And pay close attention to Martin’s opening quoted above. When looking at a feature, such as e-Commerce, consider whether you should be looking at a full featured e-Commerce platform rather than a feature that may have been cobbled onto the product as an afterthought. Remember that your primary purpose should be the management of content.
  • Whether you choose open or closed, open source or commercial, be sure that your own development team can understand and use the system with alacrity.
  • If you have a PHP team, don’t buy a .NET based CMS. And vice versa.
  • Take your time in evaluation. A quick, under-informed decision can cost you far more than you can imagine in future headaches.
  • Give your development team time to find the real problems with the CMS being evaluated and determine whether and how they can live with the problems they encounter.
  • Be sure to test the support and services teams of the vendor if you are going commercial over open source. Or if you are going open source, look for a proven and reliable partner who can guide you through the rough patches. Because no matter which CMS you choose, there will be some of those.
  • Consider licensing and support costs but don’t fall into the trap that open source is free. The efficiency of your own development and content management team using the CMS over the long haul will have a far larger impact on your overall cost of ownership.
  • Ask someone from Missouri to join your evaluation team. In other words, NEVER just accept the word of a sales representative that the CMS she is selling has the feature that you want and that it works as advertised. Like all software, there is a HUGE amount of advertising fluff and endless feature lists. Make sure that you have the sales team “show” you and then make sure that your own development team can make it work without their help and without having to contact support before you accept the claim, “Oh yes, our CMS does that.”
  • And last but not least, do your own research of satisfied and dissatisfied customers. Make some calls. Ask to speak to someone on the evaluation team where another product was chosen over the one you are considering. Ask if they evaluated the product you have your sights set on. Chances are that a few phone calls will land you a gold mine in helpful information.

Of course, you can apply these same principles to purchasing any enterprise software. And you should.

Learning from the Elevator State Machine Programming Test

In a recent job interview I was asked to build an elevator simulator. I was given the weekend to do it. I had never written a state machine before. It wasn't perfect but it passed all the tests I could come up with based on my own assumptions about the rules of behavior based on the following text from the interviewer:

Build an elevator simulator. It should have a UI that shows 5 floors, with the call buttons for each floor. The UI should also show the panel of buttons inside the elevator. As a user, I can press any floor call button (up or down), as well as elevator panel buttons to move the elevator. The elevator should move at a realistic speed (not just go instantaneously to the desired floor).

Evaluation criteria:

  1. Accuracy of the elevator state machine with various button-press scenarios.
  2. The object design of your project – how you organize the design into classes and their relationships, what design patterns you choose to use.
  3. Coding style and clarity.
  4. The UI doesn’t need to be fancy, but it needs to enable the functional requirements stated above. You can use any UI toolkit of your choice.
  5. The code should be written in C#.

Unfortunately, my assumptions were not the same as the evaluation team's assumptions, so they found some "bugs" in the behavior of my elevator. Honestly, I was not surprised. In fact, when I submitted the code, I had offered the following observations:

I did not spend much time refactoring or documenting, so you're getting to see the "first draft" of the code.

Some refactoring that I would do:

1. Create tighter assurances in the tests with required sequence of logged events rather. In running the tests, I took a shortcut and debugged through the tests to review the log entries from the state machine to verify the sequence of actions. This should be corrected.

2. Clean up each of the two state machines, AtFloor and Moving. To simplify, I might create one or two more state machine classes to make the logic rules easier to follow and remove some of the "if" fall through logic states.

3. Tighten up UI with view data model to reduce the clutter in the code or perhaps even rewrite the UI in WPF with an MVVM architecture. My choice of Windows Forms was based on time limitations and my limited experience with WPF.

4. Review and tighten up naming and coding conventions for improved readability.

The "bug" in the elevator was not the reason I did not get the job. Fortunately, the recruiter sent me the feedback she received from the interview team. This is rare. I found it helpful and will certainly take it into account in the future.

The positive and exciting thing about this entire experience was having a reason to write my first state machine in a fun exercise which I want to share with you here. This was certainly the most comprehensive programming test I've ever been given in conjunction with an interview. I applaud the employer for having such a thorough and extensive evaluation process. And I thank the interview team for their feedback. Such thoroughness really helps to determine whether a person will be a good fit for the team. And above all else, that fit is of paramount importance.

Please download the code and let me know what you think. There are clearly flaws, as I would expect of any code thrown together over a weekend, especially where the particular pattern being implemented is a first attempt. When I have time, I may want to pull this off the shelf and do the refactoring I suggested when I submitted the code. But first, I need to find an employer and settle down. I think that will happen soon.

ElevatorControl.zip (29.94 kb)

Moved from dasBlog to BlogEngine.NET

I bit the bullet today and moved from dasBlog to BlogEngine.NET after having upgraded my hosting account to .NET 4.0 and having way too many problems with my dasBlog install. I just exported the dasBlog content to BlogML.There are multiple posts about doing this.

The only thing I changed was the Global.asax code to create a permanent redirect for my dasBlog links out in the world to the BlogEngine.NET links using the following:

void Application_BeginRequest(object source, EventArgs e)
{
   HttpApplication app = (HttpApplication)source;
   HttpContext context = app.Context;
    
   // Attempt to perform first request initialization
   FirstRequestInitialization.Initialize(context);

   //redirect to ~/post/2012/03/30/DomainAspects+Inject.aspx
   //when url is ~/2012/03/30/DomainAspects+Inject.aspx
   if (context.Request.Url.AbsolutePath.EndsWith(".aspx"))
   {
      Match m = dateRegex.Match(context.Request.Url.AbsolutePath);
      if (m.Success)
      {
         string url = context.Request.Url.AbsolutePath;
         string dt = m.ToString();
         url = url.Replace(dt, @"/post" + dt);
         context.Response.RedirectPermanent(url, true);
      }
   }
}

static Regex dateRegex = new Regex(@"(?<!/post)/\d{4}/\d{1,2}/\d{1,2}/");

DomainAspects: Inject Fake PrincipalProvider and Avoid Fake HttpContext for Testing

Today I began playing with the DomainAspects project again and realized that my tests were breaking when I switched to the .NET 4.0 Framework. After a little research, it became clear. My test helper class in the previous version of DomainAspects committed a Class A coding misdemeanor. It relied on reflection to set the value of a private member on object returned by an internal method in the Thread class.

In my own defense, I did not write that code. I borrrowed it from somewhere online to allow me to set the HttpContext even when there really isn't one available when I run my tests. This was clearly bad form and came back to bite me. So I decided to eliminate the need and just added a facility in my DomainFactory class to substitute one or more of the Windsor components used by the DomainFactory.Create<T> method which is wrapped in an IDisposable via the DomainProxy<T> class being used in the tests.

Here is the simple addition to the DomainFactory. Note that we must remove these components in reverse order and then add them back since there are dependencies involved. Also note that this method will fail if you have already created an instance of a domain interface using the proxy or factory class.

/// <summary>
/// Replaces default aspect oriented operations components with client supplied components.
/// Used for testing or customizing operations withing the factory IoC container.
/// </summary>
/// <param name="principalProviderType"></param>
/// <param name="operationAuthorizerType"></param>
/// <param name="operationAuditorType"></param>
/// <param name="operationInterceptorType"></param>
/// <exception cref=""></exception>
public static void SubstituteComponents(
	Type principalProviderType = null, 
	Type operationAuthorizerType = null, 
	Type operationAuditorType = null)
{
	//set default types where param is null otherwise check for proper interface
	if (principalProviderType == null)
		principalProviderType = typeof(PrincipalProvider);
	else if (principalProviderType.GetInterface(typeof(IPrincipalProvider).FullName) == null)
		throw new ApplicationException("principalProviderType is not of type IPrincipalProvider.");
		
	if (operationAuthorizerType == null) 
		operationAuthorizerType = typeof(OperationAuthorizer);
	else if (operationAuthorizerType.GetInterface(typeof(IOperationAuthorizer).FullName) == null)
		throw new ApplicationException("operationAuthorizerType is not of type IOperationAuthorizer.");

	if (operationAuditorType == null) 
		operationAuditorType = typeof(OperationAuditor);
	else if (operationAuditorType.GetInterface(typeof(IOperationAuditor).FullName) == null)
		throw new ApplicationException("operationAuditorType is not of type IOperationAuditor.");


	if (container.Kernel.RemoveComponent("OperationInterceptor")
		&& container.Kernel.RemoveComponent("OperationAuditor")
		&& container.Kernel.RemoveComponent("OperationAuthorizer")
		&& container.Kernel.RemoveComponent("PrincipalProvider"))
	{
		container.Register(
			Component.For<IPrincipalProvider>()
				.ImplementedBy(principalProviderType)
				.Named("PrincipalProvider")
				.LifeStyle.Transient,

			Component.For<IOperationAuthorizer>()
			.ImplementedBy(operationAuthorizerType)
			.Named("OperationAuthorizer")
			.LifeStyle.Transient,

			Component.For<IOperationAuditor>()
			.ImplementedBy(operationAuditorType)
			.Named("OperationAuditor")
			.LifeStyle.Transient,

			Component.For<OperationInterceptor>()
			.Named("OperationInterceptor")
			.LifeStyle.Transient);
	}
	else
	{
		throw new ApplicationException("SubstituteComponents failed due to invoked component dependencies.");
	}
}

Once the new method was added to the DomainFactory class, I removed the TestHelper.cs file which included this very naughty code which fails in .NET 4.0 because the implementation of the Thread class changed and the GetIllogicalCallContext internal method went away.

//broken in .NET 4.0 - GetIllogicalCallContext does not exist in Thread class anymore
public static void SetCurrentContext(string fileName, string url, string queryString, FakePrincipal principal)
{
	var context = CreateHttpContext(fileName, url, queryString);
	context.User = principal;
	var result = RunInstanceMethod(Thread.CurrentThread, "GetIllogicalCallContext", new object[] { });
	SetPrivateInstanceFieldValue(result, "m_HostContext", context);
}

Now that the offending code is gone, the RegistrationServiceTests test class is broken as you see below:

[TestInitialize]
public void Initialize()
{
	//set up a fake http context with fake IPrincipal
	string[] roles =
		{
			 "Admin",
			 "User",
			 "Local Office"
		};
	TestHelper.SetCurrentContext(new FakePrincipal("Fake", "testuser", true, roles));
}

I replaced that code with this:

static bool isInitialized = false;

[TestInitialize]
public void Initialize()
{
	if (!isInitialized)
	{
		isInitialized = true;
		//only do this once per test/process run
		DomainFactory.SubstituteComponents(typeof(FakePrincipleProvider));
	}
}

And created the new FakePrincipleProvider class to create and deliver the IPrincipal as required by the IPrincipalProvider:

public class FakePrincipleProvider : IPrincipalProvider
{
	FakePrincipal principal;

	public IPrincipal GetPrincipal()
	{
		if (principal == null)
		{
			string[] roles =
			{
				 "Admin",
				 "User",
				 "Local Office"
			};
			principal = new FakePrincipal("Fake", "testuser", true, roles);
		}
		return principal;
	}
}

And now my tests pass again because my IoC container is passing along the FakePrincipleProvider to my OperationAuthorizer class.

There will be more to come with DomainAspects soon.

DomainAspects_v1_2.zip (2.97 MB)

ASP.NET MVC 4 Beta Released

I’m excited to watch the rollout of ASP.NET MVC 4 Beta and looking forward to finding the time and a good solid project to take advantage of the new mobile support and Azure SDK.

Here’s a basic list of what’s new.

  • ASP.NET Web API
  • ASP.NET Single Page Application
  • Enhancements to Default Project Templates
  • Mobile Project Template
  • Display Modes
  • jQuery Mobile, the View Switcher, and Browser Overriding
  • Recipes for Code Generation in Visual Studio
  • Task Support for Asynchronous Controllers
  • Azure SDK

I want to hear your ASP.NET MVC 4 stories. Let me know what you think about it. You may get a chance to deep dive before I do, given my current project priorities.

Situational Intelligence Leads to Certainty and Confidence

I like this quote from General Stanley McChrystal on crisis communication:

“I think when any leader faces crisis, this is true on the battlefield but I think it's also true in other areas as well, one of the things you fear most is not understanding the situation. And I think it's that uncertainty that actually is most unsettling to many leaders and causes them to be undermined in their confidence.”

Understanding the situation. If you lack context. If you lack critical knowledge. You cannot effectively lead. First, seek to understand. Listen and absorb. Contemplate. Then, and only then, act.