| Julius's profileJulius Ganns . netzkernPhotosBlogNetwork | Help |
|
December 01 The RichCommandResult PatternToday I want to show you a new pattern we developed in my last project: The RichCommandResult pattern is an approach to utilize some common features of high level programming languages to provide a more unified way of communication between application layers (especially UI and business logic) and to bypass common mistakes, especially made by unexperienced developers.
A common problem in modern OOP languages, especially statically typed ones, is out-of-band communication and the use of optional information that need to be returned from a method call (like a Success-bool). For example consider the following scenario:
A method that loads a database entry is called from the user interface: Order o = LoadOrder("HDG6734ZS");
The normal way of programming is to assume that everything went fine until an exception is thrown. But because we are in the user interface we need to make sure that the user gets a customized error message instead of a whole screen exception message. So we need to wrap our code:
try { Order o = LoadOrder("HDG6734ZS"); } catch (SomeException ex) { ShowErrorMessage(ex.Message); }
Wow, a lot of code to write here just to show a simple error to the user that may happen a lot of times. Additionally: Exceptions are really not the fastest way to distribute information between methods and not really a "defined way" either, especially between application layers (Java is the exception to the rule here because exceptions are part of a method's signature).
Exceptions are a great way for the flow of applications WITHIN a layer, but especially by taking a look at the UI, they have some drawbacks. An exception from a "deeper" layer (e.g., data access) needs to be caught within the business layer and wrapped into a new exception for the UI layer, if there should be no tight coupling between layers underneath the business layer and the UI. So you may end up with a couple of generic exceptions in the business layer that wrap specific errors from the data access -or- a lot of wrapper-exceptions that are doubled across the layers. So, what can we do about this?
The first idea crossing every developers mind is of course to return a special ReturnObject instead of void that has a properties like "Success" and the "real" return value in a generic property called "ReturnValue". But this leads to another problem. Some developers started writing code like this:
==== WRONG ====
if (UpdateOrder(order).Success && UpdateOrder(order).ReturnValue != null) ShowSuccessMessage();
The problem here is obvious: The method is called twice. Of course an experienced developer should see that, but a good software design is not based on assumptions about the knowhow of your developers. Fortunately C#, Java and others programming languages provide us with methods that normally have reference parameters when using custom objects, some even with additional features like the "out" keyword in C#.
So what is the preferred way to design a public method that is called from one layer to the other? The signature of a RichCommandResult method is as follows:
void DoSomething(object paramA, object paramB, out CommandResult<TReturnType> result);
CommandResult<TReturnType> is a generic object that contains the result of the method (which is of type "TReturnType") as well as additional information like "Success" (boolean), "TimeTaken" (TimeSpan), "HasReturnValue" (boolean), etc. So you can write your UI code like this:
CommandResult<Order> result; LoadOrder("HZS67SG67", out result); if (result.Success && result.HasResturnValue) { ShowOrderToUser(result.ReturnValue); // ReturnValue is of type "Order" in this case. } else { ShowErrorToUser(result.ErrorMessage); }
Much cleaner, isn't it? And by the way: All exceptions are caught in the layer below, the UI developer can focus on simple boolean properties in the result object and retrieve additional information from the method call. Even unexperienced developers cannot call the method twice mistakenly to work with any type of return value like they could do it in "normal" functions with a "normal" return type:
==== WRONG ====
if (LoadOrder("HDG6734ZS") != null) ShowOrderToUser(LoadOrder("HDG6734ZS"));
...which of course is also error prone in several other ways. Just to be clear: This pattern only makes sense if used wisely. It is no solution to "common" application flow tasks which needs a well designed exception hierarchy. But for the convenience and security of the UI developer it turned out to be a very good way.
Have a nice day! ASP.NET Web Development - Some Thoughts...As I started to work with ASP.NET some years go (Wow, time is passing by...), I realized that there was a huge potential using components, controls, events and the code-behind model, especially by looking at developer productivity and a familiar approach for UI developers coming from the desktop world - although my roots have always been the web world and Java EE.
However, being a Software Architect, I realized that the ASP.NET WebForms model was somewhat "dirty" compared with other approaches I worked with before, for example JSF, Tapestry and Struts as well as some others. Of course, having no real "hard" seperation between UI presentation, UI logic and especially business logic as well as data access powered the productivity of most developers, but also lead to code that was not as clean as I it could have been.
In the last years it came clear that the architectural benefits of MVC frameworks like Ruby on Rails, Struts as well as other MVC Front-Controller frameworks and also the features of better seperated component frameworks like JSF and Tapestry had some advantages in bigger projects because of the "cleaner" developmend model, but couldn't really reach the productivity of ASP.NET.
Even highly sophisticated, dyanmic languages like Ruby and well-designed frameworks like Rails, which I totally love, did not lead to the same results in functionality, security (e.g., exception and error handling) and productivity.
I have to admit that I'm really the "tool guy" when it comes to software development: I want to be able to use any tool out there in the appropriate way to solve a problem the best way. So I came across MonoRail and lately I started playing aroung with ProMesh while searching through the .NET web world, but ScottGu's team had done such a remarkable job by providing great tools and features to overcome the minor architectural weaknesses in ASP.NET that there was no real chance for other frameworks to compete with a well-designed ASP.NET application with wisely-used components and features (the focus is on "well-designed" and "wisely-used", by the way).
Now ASP.NET MVC is coming. Of course I'm the first one to get my hands on the CTP, and I'm quite sure that there is indeed a lot of things one can do with this new framework, especially in combination with the upcoming DLR and languages like IronRuby, IronPython and others. But I wonder if it's really the new way of developing .NET web applications, or more like an iterims addition in combination with WebForms and its controls to overcome some of the architectural drawbacks until the development has moved completely to "real" AJAX apps with much more client-side logic.
In my oppinion, the MVC approach to AJAX by using server-generated snippets and sending them to the client ("partial page-rendering") cannot compete with a "pure" AJAX application that uses server-side services and provides some kind of real "desktop-feeling". Using components, XML-Script and controls the way ASP.NET AJAX does it, seems to me the right way to outperform the "classic" MVC way of web development over time.
Okay, enough thoughts for now.
Enjoy the weekend! |
|
|