This is how I would think of an application at the very basic level:
Now this works great. But one thing that is missing in this picture is Exception Handling. In many cases we pay very less attention to it and take it as "we'll cross that bridge when it'll come to that". We can get away with this as in many application as exceptions does not stop it from being in the state "is the application working" as long as we code it carefully and at the very least handling the exceptions in code blocks.
This works. But we end up having try catch and if else everywhere and often with messy or no direction to what type of exception is to be handled where and how. Nonetheless, when it comes down an enhancement that depends upon different types exceptions, we will end up writing/modifying code every where, resulting in even messier code. I'm sure no one wants that. Even, in scenarios, a custom handler is not the answer either. Cause this way we will still need to make changes all over our code where we have used that handler.
The hero that can save us from this predicament is this namespace: á•™(`▿´)á•—
Microsoft.Practices.EnterpriseLibrary.ExceptionHandling
So the idea is very simple.
- Think about what kind of exceptions may occur in you application like read exception, write exception, heck even not implemented exception. (at the very least the "awesome" application can have "awesomegenericexception"
- Define a policy for each. For each policy we'll have our own implementation or channel in to an existing implementation.
- apply these policies where necessary.
How it looks:
- in config:<configSections>
<section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<exceptionHandling>
<exceptionPolicies>
<add name="AwesomeExceptionPolicy">
<exceptionTypes>
<add name="All Exceptions" type="System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="ThrowNewException">
<exceptionHandlers>
<add name="Wrap Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WrapHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
exceptionMessage="Awesome Exception Occured." exceptionMessageResourceType=""
exceptionMessageResourceName="Awesome Exception Occured. This is so awesome that you are going to get a text message for it :)."
wrapExceptionType="Awesome.Lib.Exceptions.AwesomeExceptionPolicyImpl, Awesome.Lib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>
</exceptionPolicies>
</exceptionHandling>
- in code "the boss of exceptions":public class ExceptionManagerFactory : IProvider
{
ExceptionManager exceptionManager;
public Type Type
{
get
{
return this.GetType();
}
}
public object Create(IContext context)
{
return GetExceptionManager();
}
public ExceptionManager GetExceptionManager()
{
if (exceptionManager == null)
{
IConfigurationSource config = ConfigurationSourceFactory.Create();
ExceptionPolicyFactory factory = new ExceptionPolicyFactory(config);
this.exceptionManager = factory.CreateManager();
}
return this.exceptionManager;
}
}
- in code "the injection":Kernel.Bind<ExceptionManager>().ToProvider<ExceptionManagerFactory>().InSingletonScope();
- in code "the implementation":public class AwesomeExceptionPolicyImpl : ApplicationException
{
public AwesomeExceptionPolicyImpl(string message)
: base(message)
{ } public AwesomeExceptionPolicyImpl(string message, Exception innerException)
: base(message, innerException)
{
Console.WriteLine("to err is human :)");
}
}
- in code "the use":
ExceptionManager exManager; // injection. Can be done in the super duper base class.
exManager.Process(() =>
{
YouMyAwesomeTask();
}, "AwesomeExceptionPolicy");
private void YouMyAwesomeTask()
{
// do the awesome task.
}
Here, I am only implementing the policy for System.Exception. But this can be for other exception types as well. Where the type does not need to be anything more than just a type or even just a message.
- So when it will come down to future modification we will only have to touch one class. Or in the worst case very little change in the code.
- And the overall outcome is even better you write less code. While implementing your method you only think about what policy does it fall under. How that is handled/implemented that's not your problem.
- Even you can make up policy as you go and implement them at later point or channel them to one implementation.
- And ofcourse, CLEAN CODE.
\ (•◡•) /
Now this works great. But one thing that is missing in this picture is Exception Handling. In many cases we pay very less attention to it and take it as "we'll cross that bridge when it'll come to that". We can get away with this as in many application as exceptions does not stop it from being in the state "is the application working" as long as we code it carefully and at the very least handling the exceptions in code blocks.
This works. But we end up having try catch and if else everywhere and often with messy or no direction to what type of exception is to be handled where and how. Nonetheless, when it comes down an enhancement that depends upon different types exceptions, we will end up writing/modifying code every where, resulting in even messier code. I'm sure no one wants that. Even, in scenarios, a custom handler is not the answer either. Cause this way we will still need to make changes all over our code where we have used that handler.
The hero that can save us from this predicament is this namespace: á•™(`▿´)á•—
Microsoft.Practices.EnterpriseLibrary.ExceptionHandling
So the idea is very simple.
- Think about what kind of exceptions may occur in you application like read exception, write exception, heck even not implemented exception. (at the very least the "awesome" application can have "awesomegenericexception"
- Define a policy for each. For each policy we'll have our own implementation or channel in to an existing implementation.
- apply these policies where necessary.
How it looks:
- in config:<configSections>
<section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<exceptionHandling>
<exceptionPolicies>
<add name="AwesomeExceptionPolicy">
<exceptionTypes>
<add name="All Exceptions" type="System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
postHandlingAction="ThrowNewException">
<exceptionHandlers>
<add name="Wrap Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WrapHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
exceptionMessage="Awesome Exception Occured." exceptionMessageResourceType=""
exceptionMessageResourceName="Awesome Exception Occured. This is so awesome that you are going to get a text message for it :)."
wrapExceptionType="Awesome.Lib.Exceptions.AwesomeExceptionPolicyImpl, Awesome.Lib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</exceptionHandlers>
</add>
</exceptionTypes>
</add>
</exceptionPolicies>
</exceptionHandling>
- in code "the boss of exceptions":public class ExceptionManagerFactory : IProvider
{
ExceptionManager exceptionManager;
public Type Type
{
get
{
return this.GetType();
}
}
public object Create(IContext context)
{
return GetExceptionManager();
}
public ExceptionManager GetExceptionManager()
{
if (exceptionManager == null)
{
IConfigurationSource config = ConfigurationSourceFactory.Create();
ExceptionPolicyFactory factory = new ExceptionPolicyFactory(config);
this.exceptionManager = factory.CreateManager();
}
return this.exceptionManager;
}
}
- in code "the injection":Kernel.Bind<ExceptionManager>().ToProvider<ExceptionManagerFactory>().InSingletonScope();
- in code "the implementation":public class AwesomeExceptionPolicyImpl : ApplicationException
{
public AwesomeExceptionPolicyImpl(string message)
: base(message)
{ } public AwesomeExceptionPolicyImpl(string message, Exception innerException)
: base(message, innerException)
{
Console.WriteLine("to err is human :)");
}
}
- in code "the use":
ExceptionManager exManager; // injection. Can be done in the super duper base class.
exManager.Process(() =>
{
YouMyAwesomeTask();
}, "AwesomeExceptionPolicy");
private void YouMyAwesomeTask()
{
// do the awesome task.
}
Here, I am only implementing the policy for System.Exception. But this can be for other exception types as well. Where the type does not need to be anything more than just a type or even just a message.
- So when it will come down to future modification we will only have to touch one class. Or in the worst case very little change in the code.
- And the overall outcome is even better you write less code. While implementing your method you only think about what policy does it fall under. How that is handled/implemented that's not your problem.
- Even you can make up policy as you go and implement them at later point or channel them to one implementation.
- And ofcourse, CLEAN CODE.
\ (•◡•) /
Comments
Post a Comment