Introduction
Developers in .NET sometimes come from scripting language environments that are not strong on Object Oriented Methodologies. OO methodologies like refactoring and using design patterns can be intimidating and the value for the developer is hard to see. What developers new to the OO world, and even more seasoned developers need to understand is that good design is not beyond scope in any project. Good habits simply must be learned that will make the developer a better designer.
In that mind set, I am submitting the first of several "how to" real world examples, used in my professional life, on how to use patterns in a simple, easy to follow manner. Many of us have ended up either writing or working on in-line, scripting based code. Taking some ideologies from refactoring methodology, is not necessarily a bad thing. Of course, when you are first writing an algorithm or a series of logic statements, it seems easier to start with if....then....else
. But as you continue to expand this code to more complex forms, this model can quickly become unmanageable. This is where refactoring and design pattern methodology can play an important and useful part in simplifying, enhancing and making code more useable (and understandable) to those who practice good OO design.
This article details a real world example of how to use facade patterns to help you deal with a modular code system, such as business layer algorithms, or any code which you wish to extract into its own assembly/namespace and allow only specific access to from outside the assembly/namespace. The strictest definition of a facade pattern is any code you wish to provide a single access point to, limiting the access points to other classes and parts of code that you do not wish to be accessed outside of the assembly/namespace.
Background
I have used facades usually in modular code for either business layers or handy API assemblies. In this example, which is straight from real world code I had developed in my professional life, I illustrate how to use a facade pattern to create a piece of modular functional code.
How to use the code
.NET uses the class and method modifier internal
to restrict access to classes and methods in an assembly to have access only internally to the assembly/namespace where the class or method exists. Using this class modifier, we can restrict any and all classes we wish to remain hidden to the code executing outside our module assembly/namespace.
We start off with some functional code that we wish to extract into our module assembly. Keep in mind when designing a modular system, you should decide at the outset which methods and/or classes you wish to give the code executing outside the assembly/namespace access to, and which classes you wish to hide.
public class DoSomeWork
{
public DoSomeWork(WorkerObject workerObject)
{
}
}
Next we build our basic facade and interface classes, marking method modifiers we wish to have external access to as public
. First we need to build a contract or interface that allows access to our facade class. The IDoSomeWork
facade will define how the code outside the assembly will access and work with your module code.
Note: Notice that no modifier is necessary on the interface method DoSomeWork
. This is because methods on an interface are always implicitly public
to the interface's level of access:
namespace DoSomeWorkModule
{
public interface IDoSomeWork
{
void DoSomeWork(WorkerObject workerObject);
}
}
Next we build our facade class, DoSomeWorkFacade
, which will contain the actual functional code, or pointers to other internal
classes in the assembly, that actually do the work. Notice that on the DoSomeWork
method we add the IDoSomeWork
interface as a map to the method. This declares that only the interface may access this method:
namespace DoSomeWorkModule
{
public class DoSomeWorkFacade : IDoSomeWork
{
public void IDoSomeWork.DoSomeWork(WorkerObject workerObject)
{
}
}
}
To declare for usage, you must do so thus:
IDoSomeWork doSomeWorkFacade = new DoSomeWorkFacade();
doSomeWorkFacade.DoSomeWork(workerObject);
Notice that we called the DoSomeWork
method by instantiating DoSomeWorkFacade
facade and setting its access contract with IDoSomeWork
. Since we mapped the DoSomeWork
method to the IDoSomeWork
interface, we can only call this method as stated in the interface contract. We cannot, for example, call any method mapped to the interface thus:
DoSomeWorkFacade doSomeWorkFacade = new DoSomeWorkFacade();
doSomeWorkFacade.DoSomeWork(workerObject);
Now that we have set up our facade classes, we can deal with some of the other classes, related to and supporting our facade. First let's deal with the class passed into the DoSomeWork
method, WorkerObject
. This class is a simple data object, and is part of the namespace for the module DoSomeWorkModule
. Its modifiers are public
even though it is contained in our module, because we want the executing code outside the assembly to have access to it. The executing code can then pass this object in as a parameter to our facade:
namespace DoSomeWorkModule
{
public class WorkerObject
{
private object _obj1;
public object Object1
{
get{return _obj1;}
set{_obj1 = value;
}
}
}
We will also have some other classes, perhaps based on different patterns, that exist inside the assembly, that have internal
access modifiers. These classes are support classes that help the code internal to the facade do its work. Here we have as an example a class loosely based on the mediator pattern named DoSomeMediation
. DoSomeMediation
registers a series of WorkerObject
s within, and contains a method to send messages to all the WorkerObject
s it contains, in effect, mediating between the registered objects. (More on the mediator pattern, will be covered in a later article). The thing to notice here is that DoSomeMediation
is marked with the modifier internal
. This prevents access to the class outside of the namespace, which will be called from the DoSomeWork
method on the DoSomeWorkFacade
:
namespace DoSomeWorkModule
{
internal class DoSomeMediation
{
internal void Register(WorkerObject workerObject)
{
}
internal void Send()
{
}
}
}
Expanding the example
A reader posted a good question: how do you keep users from accessing the constructor of the implementation class? The answer is by creating the interface contract for the class via a factory. You would in this case mark the DoSomeWorkFacade
facade class as internal
, and have the factory build the implementation. Of course your factory create method has to be externally accessible, but the DoSomeWorkFacade
class can now be marked internal
:
namespace DoSomeWorkModule
{
internal class DoSomeWorkFacade : IDoSomeWork
{
internal void IDoSomeWork.DoSomeWork(WorkerObject workerObject)
{
}
}
public class DoSomeWorkFactory
{
public static IDoSomeWork GetFacade()
{
IDoSomeWork doSomeWorkFacade = new DoSomeWorkFacade();
return doSomeWorkFacade;
}
}
}
Points of interest
This is the second installment in the series I am writing on real world design patterns. All examples and the bulk of this article are taken from my professional experience as an architect. The examples given are templates only, and the designer must keep in mind that they are the ones who must decide where different patterns, if any, may be best used in their code.
Deciding to perform a refactoring effort from the existing code to a pattern must be weighed on the necessity and need of the code itself. Patterns are only design templates, helpers to accommodate better overall design. I must stress that making an effort to use patterns will strengthen your overall design ability, but like your basic coding skills, it is something that is to be learnt and cultivated.
If this or any other in this series on design patterns is helpful or you have questions or comments please e-mail me at chris.lasater@gmail.com.
History
This is the third revision and is the second installment in a series.