Wednesday, July 22, 2009
Implementing Plug-Ins with a DI Container
If you are building a highly extensible application, the right answer these days seems to be to look into MEF. It is a very flexible approach to extensibility and plug ins that works for 3.5 and will become part of the .NET Framework in 4.0. However, sometimes you just need a simple plug in capability to load some components provided by others. If there is any chance those plug ins will depend on each other and need to talk to each other, bite the bullet and learn and use MEF. But if they just need to be loaded up and called, you can use a simple factory to get the job done. About 4 years ago, I put together a little sample of doing this with a generic factory class here. A similar requirement came up with a customer this week, but with one twist: we were already using a DI container (Unity) and the plug ins that were going to load were going to have dependencies on some objects and services that the DI container already knew about. Since the container is really a generic factory itself, I decided to put together a little sample of using Unity as a plug-in factory and thought I would share it here. Defining the Plug-ins The first step to a plug-in architecture is to define the common interface(s) that the plug-ins themselves will implement. Say you have this interface definition in a common library: public interface IPlugIn
{
void DoSomething();
}
Then you define some implementations of that interface in other class libraries (the plug in libraries):
public class PlugIn1 : IPlugIn
{
public PlugIn1(ILogger logger) { }
public void DoSomething()
{
Console.WriteLine("PlugIn1 called");
}
}
Note that this plug in has a dependency on some service (ILogger) that our DI container will know about.
Using the Container As the Plug-In Factory
Now all you need to do is use the ability to configure the Unity container through a config file to have the construction of those plug ins loosely coupled from the code.
Define the config info to configure the container with the plug in types, as well as the dependent types:
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration, Version=1.2.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<unity>
<typeAliases>
<!-- Lifetime manager types -->
<typeAlias alias="singleton"
type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,
Microsoft.Practices.Unity" />
</typeAliases>
<containers>
<container>
<types>
<type type="Common.IPlugIn, Common" mapTo="PlugIns.PlugIn1, PlugIns" name="PlugIn1"/>
<type type="Common.IPlugIn, Common" mapTo="PlugIns.PlugIn2, PlugIns" name="PlugIn2"/>
<type type="SomeDependencyLibrary.ILogger, SomeDependencyLibrary"
mapTo="SomeDependencyLibrary.Logger, SomeDependencyLibrary" >
<lifetime type="singleton" />
</type>
</types>
</container>
</containers>
</unity>
</configuration>
Then just configure the container and resolve the plug-ins through a call to ResolveAll:
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section =
(UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(container);
IEnumerable<IPlugIn> plugIns =
container.ResolveAll<IPlugIn>();
foreach (IPlugIn plugin in plugIns)
{
plugin.DoSomething();
}
And viola. you have a simple plug-in factory using the container.
Sunday, July 12, 2009
Comments on The Myth of Developer Productivity
Scott Bellware put together a great post emphasizing the importance of organizational productivity over developer productivity that I wanted to point people to and make some additional comments on. In his post, Scott points out the pitfalls of focusing only on developer productivity as a way to ship your product faster. He elaborates on the fact that if you don’t have a good quality-focused process and organization, the short term gains (or local optima as he describes them) created by developer productivity or efficiency tools may actually compound your problem in several ways. Organizational Productivity I totally agree with several things Scott points out in his post. First, a lot of the customers I deal with in consulting do have immature processes and organizations, so they need to fix those first and foremost if they really want to ship higher quality products faster. Following agile practices including the following are some of the minimum bars I think development teams should be targeting for most business applications: - Practicing Scrum or having daily stand up meetings to facilitate team communications and collaboration
- Practicing Pair Programming or at a minimum having diligent code reviews on all production code
- Practicing TDD/BDD/DDD or at a minimum having a high degree of unit test coverage combined with a good loosely coupled design
- Documenting requirements in a light weight, but easy to understand and location form (user stories, bullet lists, work items all suffice if done coherently)
- Having a good CM process including good source control tools
- Having an automated build process that runs nightly at a minimum, or better yet trending to continuous integration
There is a lot more to having a good agile process in place than I can document here, but the point is that too many teams recognize that these are things they should be doing, but they never get around to establishing as a repeatable part of their process. Then they hear about developer productivity tools and think that just by using those, they will somehow overcome the organization-level lack of productivity with the micro-productivity enhancements that developer productivity tools can often have. The Hazard of Developer Productivity Tools Also as Scott points out, when used blindly, some developer productivity tools can actually cause grave damage to product-level productivity. One example of this includes some of the developer productivity tools in Visual Studio, specifically some of the code produced by designers and code generation. This has gotten better from version to version, but there is still the tendency to put things into Visual Studio that demo well and might be OK for toy applications, but should never be used for serious applications. For example, the SqlDataSource in ASP.NET encourages developers to drag and drop their way to a functional data driven page. Looks great, and you are done in minutes. Developer productivity nirvana. But what happens after that? You end up with hundreds of these scattered across your project, each with embedded markup tightly coupling the page to the database schema. Bad, bad, bad for overall productivity in developing a product because it is a maintenance nightmare. But these kind of features are often hyped in the VS demos as if it will make you able to ship your product so much faster. It might let you get a simple first version out the door faster. But even the first version of a moderately complex app will suffer in timeline as the schema changes throughout the development cycle and you have to keep tracking down the resulting breakage in the tightly coupled pages. The remedy is taking the time up front to put a good layered design in place, and use the right developer productivity tools in the right way (i.e. bind an ObjectDataSource to the domain objects coming out of a repository) to speed up the coding process slightly, but not end up with messy un-maintainable code from using them. Another hazard I see with developer productivity tools (VS ones in particular) are that especially for less experienced developers, it tends to teach them that if they can’t do it through the tool, it can’t be done. I had this at a customer site the other day. We were using a mapping component, and the developer came in complaining something that we needed to do wasn’t supported by the component. After drilling into the problem, it turned out that what the developer really meant is “my Visual Studio integration for that component is not working, and if I can’t drag and drop it and hook things up in the designer, I have no clue how to code against the component itself”. If you are going to use any developer productivity tool, the developers have an absolute responsibility for understanding what the generated code does, and how to write that code themselves if the tool is not available or is not doing things quite right. If they are going to use features that produce code that is not great for long-term productivity, they need to fix the code to make it more maintainable as soon as the code is generated. If fixing the generated code right then takes them longer than it would have to code it all by hand, then they shouldn’t be using the tool in the first place. Another example is the WCF proxy generation in Visual Studio. While it is great for quickly the code in place to make calls to a service that exposes metadata, the proxy code that it generates is usually much more verbose than it needs to be, and it can totally garbage up your app.config or web.config file with unnecessary configuration elements that become your maintenance burden. It is usually more productive from an overall productivity perspective to do what we call “hand coding” the proxy. The Benefit of Developer Productivity Tools and Why You Should Still Use Them - Correctly However, that being said, I am a firm believer in not wasting developers time, as well as trying to keep developers focused on the logic they are implementing, instead of spending too much time banging on the keyboard and worrying about the structure of the code instead of its content. So even when I say “hand coding” above, I would prefer to use a developer productivity tool such as CodeRush + Refactor, ReSharper, or just Code Snippets in Visual Studio to output clean, templated code for those places where repetitive coding patterns are required. If possible, I would then look for opportunities to refactor some of that repetitive code into base classes or helpers, but that is not always possible. So I actually often say that I firmly believe that every developer should have a copy of CodeRush+Refactor or ReSharper on their machine, and should spend a little time learning how to use the basic features of those products right. As Scott points out, doing so is not going to affect your overall timeline one bit if you don’t already have a highly efficient and streamlined organizational process. And if the developers don’t understand the code that is being spit out or when it is appropriate, it is again a liability , but that again comes back to professional responsibility of being a good developer. But at a minimum, I do think the tools mentioned above save the developers tons of time in terms of not wasting time banging out snippets of code character by character, but instead lets them spit out the right code with minimal keystrokes. This frees their time and their mind to focus more on the logic of the code instead of the structure. It also lets them blaze through throw away implementation of prototypes and spikes much faster than if they didn’t have those tools, and if done right, that code is getting dumped once you figure out what you are going to do and how to do it anyway. Using CodeRush/Refactor or ReSharper also tend to produce better consistency in the code, because if the tool templates are spitting the small structural elements out, those elements are more likely to be coded consistently across developers. Finally, both of those tools have great features for continuous refactoring of code to clean up things like redundant/unused declarations, replacing string concatenation with string.Format, and hundreds of other things that might otherwise be missed, or just take more time to do manually than they do using the tool. Wrap Up So bottom line, I agree with almost everything Scott says in his post. I just think in some places it paints an overly negative picture of developer productivity tools and could lead someone like a product manager to say “I don’t need to buy my developers these tools because they won’t help anyway”. If you don’t focus first at the process level, you still won’t ship your products any faster by using developer productivity tools. But I think with the right tools and the right approach to using them, you will still improve the quality of the code the developers are producing by using these tools, and that is worth it in its own right. And you may get through the experimentation implementation portions of your lifecycle a little faster as well. But don’t fool yourself into thinking that just throwing these tools at the developer is all you need to do. And also approach any developer productivity tool with jaded optimism and get a real understanding of what it is producing and what the long term impact of that code is before you think it is really going to save you any time before committing to using it for production coding.
Saturday, May 30, 2009
Debuggable Self-Host Windows Service Projects
When developing self-hosted WCF services, you really need two things: - A windows service project that will be the host for the deployed environment.
- A console self-host project for easy debugging while developing the service.
Yes, there is also the option to use a WCF Service Library project with its associated WcfServiceHost.exe process that self hosts the service for debugging. However, I have run into too many occasions where something is going wrong and not having direct access to the hosting code wastes more cycles than it takes to set up my own service host, so other than quick demos, I never use the WcfServiceHost.exe in production development. Having two separate projects to address 1 & 2 above is not really that great either, but if you try to run a service project in the debugger, you get an error telling you it can only be run through the services panel in Windows. However, through a quick and easy pattern, you can make your service projects so they run as a console for development, but run as a service just fine when installed. Step 1: Create a Windows Service project for the self host environment. This is just the standard selection in the project dialog for a Windows Service project. Once you have your service class, rename it as appropriate and right click on the designer surface to add an installer class for the service. Standard stuff here. Step 2: Implement your hosting code in a separate class from the service class itself. For example, here is a very simple hosting class that can be used for any service in any project (with some appropriate exception handling and logging added in for production purposes): public class SelfHost<T>
{
ServiceHost m_Host;
public void Start()
{
m_Host = new ServiceHost(typeof(T));
m_Host.Open();
}
public void Stop()
{
m_Host.Close();
}
}
From the service class itself, you can just instantiate an this class and call its Start and Stop methods.
public partial class SimpleServiceHostService : ServiceBase
{
SelfHost<SomeService> m_Host = new SelfHost<SomeService>();
public SimpleServiceHostService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
m_Host.Start();
}
protected override void OnStop()
{
m_Host.Stop();
}
}
Now when you install this service, the service host will be started and stopped through the services panel or automatically depending on the service configuration.
Step 3: Modify the Main method to start conditionally as a Console or a service.
Modify the default main declaration with no parameter to the signature for a main that takes a string[] of arguments. If arguments are present, run the code as if you are in a console app. If no arguments, call the default code for starting it as a service. For the console host mode, just call the Start and Stop methods on an instance of your host class just like the windows service did.
static void Main(string[] args)
{
// Run as console if there are command line arguments
if (args.Length > 0)
{
SelfHost<SomeService> host = new SelfHost<SomeService>();
host.Start();
Console.WriteLine("Press Enter to Exit...");
Console.ReadLine();
host.Stop();
}
else // run as service
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new SimpleServiceHostService()
};
ServiceBase.Run(ServicesToRun);
}
}
Step 4: Modify the project properties to be a console application and add a debug command line parameter.
That is basically it. Change the code shown above to use your service type, add an app.config with the appropriate WCF service code, and you are ready to run as a console app in the debugger, but when you build and install your service as a service, it will run fine as that as well.
You can download a full sample application here.
Wednesday, May 13, 2009
TechEd SOA401 – Developing Service Oriented Workflows
This morning I am giving the subject session at TechEd. For those of you that attended, thanks! You can probably jump to the link at the bottom for the demos unless you want a quick review of what we covered by reading the rest of this post. This session discusses .NET 3.5 Workflow Services, and I also touch on what is different in .NET 4.0 throughout and at the end. I also have a brief discussion at the end about cloud workflows, using workflow activities from .NET Services and running workflows in the cloud with Windows Azure. In the talk, I demonstrate the use of the ReceiveActivity for exposing service operations from a workflow. I show how to add the receive activity to a workflow, hook it up to a service contract and the operations on that contract, how to bind the incoming parameters to other workflow properties and how to retrieve the return result from workflow properties through a binding. I then show how to host the workflow as a service using the WorkflowServiceHost class, how to get a reference to the WorkflowRuntime from the host (to hook up to workflow events), and how to configure the right bindings (context bindings) to expose the workflow. Then I write a quick client that is able to call the workflow to get it running and pass parameters to it. Then I jump to a more complicated workflow that represents a loan application process as a state machine workflow. The loan application is submitted through a service call, and then approve or reject actions can be taken through service calls. I show how calls from the same client work out automatically through the passing of the instance ID through the context bindings, and how to allow multiple clients to interact with the same workflow by setting and getting the instance ID out of the context. Then I show that the loan application workflow also needs to make service calls out to another credit checking service. So I demonstrate how you can use a SendActivity to act as a dynamic proxy in the workflow to call another service. Like the ReceiveActivity, you use bindings on dynamic properties to provide values for the outgoing parameters and to deal with any returned values. I also discuss the limitations of the SendActivity and how to work around it by creating a simple custom activity to encapsulate a normal WCF proxy over which you have complete control. Then I show an application that is composed of two workflows, a parent workflow and a child workflow. The parent invokes the child workflow and gets results back from the child. The trick with this scenario is how you need to pass the context to the child workflow of the receive activity that the call will come back into in the parent workflow so that the workflow runtime can reassociate the incoming call with the right instance and right receive activity. If you want to take a look at the demos that do all of the above, here you go.
Thursday, May 07, 2009
NoVa Code Camp – 23 May
Update: Apparently I found a wormhole this morning and stated January instead of May. That would be May 23!
We have a code camp coming up on Saturday 23 May in Northern Virginia at the Reston Microsoft Training Center at 12012 Sunset Hills Rd, Reston, VA. There is a great line up with 4 tracks and over 20 speakers. I’ll be giving a session on Developing Service Oriented Workflows, come out and expand your brain!
Friday, May 01, 2009
Selecting the Right Client Technology Interview
Last year at TechEd, I was interviewed for ARCast TV about selecting the right client technology for your application, which I also gave as a breakout session at the conference. I don’t know why it took almost a year to produce, but that interview is now available. You can check it out here: http://channel9.msdn.com/shows/ARCast.TV/ARCastTV-Brian-Noyes-on-Selecting-the-Correct-Client-Technology/ Some of the key points from the discussion included: - WPF is really your best choice for any new smart client application development over Windows Forms if you care about building your team’s skill set where it matters for the long term. - Windows Forms is still relevant for evolving existing applications, and even for new applications that are intensive on data editing but not visualization, where you have an existing team with deep knowledge in Windows Forms but no experience with WPF, and where you can justify that you will never need to have enhanced graphics, user experience, or advanced data visualizations. - Silverlight is the way to go for anything where you want both broad reach in the browser and rich graphics. Particularly with the announcements of features in Silverlight 3 since this interview occurred, there are many applications that in the future with Silverlight 3 will be just as well off as a Silverlight application as they would be with WPF for businesses. - ASP.NET (using AJAX features for better user experience) can still go a long way in delivering what you need for broad reach applications, and is certainly the way to continue if you have a good investment in web application development with .NET. - Mixing ASP.NET and Silverlight for where their strengths lay is the sweet spot for web - Starting to invest in WPF knowledge now is the right choice for the future with smart client development Nothing too earth shattering will cause Nostradamus to rise from his grave, but hopefully helps cement some tough technology choices for people who were not sure which direction to head.
Wednesday, April 22, 2009
Building Composite WPF Applications at Evansville .NET Users Group
I presented a session last night at the Evansville .NET Users Group in Indiana on building composite applications with Prism 2. It was a great little group with a lot of really good questions. For those that were there, thanks! For those who are interested, here are the slides and demos: Slides Demos
Composite Extensions for Prism 2
I figured that since I wrote my original composite extensions for Prism 1 on an airplane, I should keep up the tradition. On the way home from speaking in Evansville Indiana last night (not surprisingly on Prism), I got all the code in my composite extensions updated to Prism 2. So if you like the modularity and pub-sub events story from Prism and would like to be able to do those same things in a Windows Forms or other kind of .NET application, you can easily do so now with these CompositeExtensions. These extensions allow you to use the modular loading patterns and capabilities of Prism as well as the pub/sub events in a Windows Forms application, or any other kind of application (even console apps, WCF services, etc.). The key pieces remain the same: A CompositeEvent class that has all the same capability as the CompositePresentationEvent class in Prism2, but is not tied to the WPF libraries at all. For the UI thread dispatching capability, it uses the SynchronizationContext class (which is used under the covers by both WPF and Windows Forms, so this class will also work with WPF). A SimpleUnityBootstrapper class that removes the tie to WPF in the bootstrapper by removing the creation of the shell and the region adapter stuff. The code also include a sample Windows Forms application that uses the extensions to load a module and fire and handle pub-sub events. As mentioned in the original post, I also demonstrate a simple way of using the DI container (Unity in this case) to achieve a Region-Manager like UI composition ability in Windows Forms. Check it out and let me know if you have any feedback.
Thursday, March 05, 2009
TFS Build Node Problem Fix
Yesterday (in the midst of trying to get some builds done to get to a release), the Build node of my Team Explorer window for all Team Projects under my main user account went stupid and was displaying a red X for unavailable. Very frustrated, I did some searching and found very little other than one post suggesting that killing my user account and recreating it from scratch would clear the problem. That would also have cost me hours of reconfiguring other programs and settings that are customized under my account, so I dismissed that. Based on that though, I went and created a separate user account and was able to run builds from there and switch back and forth with Switch User to get through the day. The sweet thing was that when I fired up VS 2008 this morning and went to Team Explorer with no project loaded, I noticed a bunch of stuff get spit into my output window. Looking closely, it was a nice little error message from Team System telling me the BuildPackage was not being loaded due to previous errors, and if I wanted to have it try again, just launch VS from the command prompt with the following line: devenv /resetskippkgs Worked like a charm and my environment is totally happy again. You gotta love software that detects its own problems and suggests simple things that actually work to fix it. Well done VSTS team!
|





| September, 2010 (2) |
| August, 2010 (5) |
| July, 2010 (6) |
| June, 2010 (8) |
| May, 2010 (2) |
| April, 2010 (2) |
| January, 2010 (1) |
| December, 2009 (3) |
| November, 2009 (2) |
| October, 2009 (3) |
| September, 2009 (3) |
| August, 2009 (2) |
| July, 2009 (3) |
| May, 2009 (3) |
| April, 2009 (2) |
| March, 2009 (1) |
| February, 2009 (2) |
| January, 2009 (2) |
| December, 2008 (1) |
| November, 2008 (2) |
| October, 2008 (5) |
| September, 2008 (4) |
| August, 2008 (2) |
| July, 2008 (1) |
| June, 2008 (2) |
| May, 2008 (2) |
| April, 2008 (3) |
| February, 2008 (6) |
| January, 2008 (3) |
| December, 2007 (1) |
| November, 2007 (1) |
| October, 2007 (5) |
| September, 2007 (1) |
| July, 2007 (3) |
| June, 2007 (8) |
| April, 2007 (2) |
| March, 2007 (4) |
| February, 2007 (1) |
| December, 2006 (2) |
| November, 2006 (9) |
| October, 2006 (5) |
| September, 2006 (3) |
| August, 2006 (2) |
| July, 2006 (4) |
| June, 2006 (5) |
| May, 2006 (10) |
| April, 2006 (4) |
| March, 2006 (2) |
| February, 2006 (12) |
| January, 2006 (7) |
| December, 2005 (2) |
| November, 2005 (15) |
| October, 2005 (6) |
| September, 2005 (7) |
| August, 2005 (3) |
| July, 2005 (10) |
| June, 2005 (11) |
| May, 2005 (7) |
| April, 2005 (8) |
| March, 2005 (6) |
| February, 2005 (2) |
| January, 2005 (6) |
| December, 2004 (3) |
| November, 2004 (5) |
| October, 2004 (2) |
| September, 2004 (5) |
| August, 2004 (13) |
| July, 2004 (6) |
| June, 2004 (14) |
| May, 2004 (17) |
| April, 2004 (12) |
| March, 2004 (8) |
| February, 2004 (10) |
| January, 2004 (14) |
| December, 2003 (9) |
| November, 2003 (13) |
| October, 2003 (3) |


Sign In
|