Showing posts with label Best Practices. Show all posts
Showing posts with label Best Practices. Show all posts

Monday, January 23, 2012

Check -> Argument -> Condition: .NET 4.0 Code Contract, CuttingEdge.Conditions, Shrinkr Check


An early part of designing an effective, maintainable system is consistency. The more consistent your applications responses, the better it will be in the long term. One place that breeds inconsistency in parameter validation, and exception throwing.

So I set out to find a condition checking library capable of accomplishing a few simple goals:

  • Must provide a simple interface for validating conditions (object and state)
  • Must have a consistent response algorithm or structure
  • Must be written in .NET 
  • Must be open-source

With the additional side-goals (or bonus points):

  • A fluent interface
  • Documentation or code samples
  • NuGet package
There are plenty of libraries and source-code examples out there that accomplish these goals:

  • .NET 4.0 Code Contracts - Code Contracts provide a language-agnostic way to express coding assumptions in .NET programs.. The Common Language Runtime (CLR) team is introducing a library to allow programming with contracts in the Microsoft .NET Framework 4. 
  • Shrinkr's Check -  "a Url Shortening Service which demonstrates some of the best practices in developing real life web applications." and contains a fluent checking class structure.
  • CuttingEdge.Conditions - CuttingEdge.Conditions is a library that helps developers to write pre- and postcondition validations in their C# 3.0 and VB.NET 9.0 code base. 
  • GuardQ - validating function arguments.
  • Fluent Validation - "A small validation library for .NET that uses a fluent interface and lambda expressions for building validation rules for your business objects."
  • FluentValidation for .NET 2.0 - Rework of the popular FluentValidation library to work in .NET 2.0. There is one minor syntax change and the LinqBridge (lambda syntax for 2.0) library is required, so please read the docs. Namespaces and licenses are similar to FluentValidation.
Here are a few:
CuttingEdge.Conditions

CuttingEdge. Condition Validation Extensions
Conditions is an open-source project (available on CodePlex) that "CuttingEdge.Conditions is a library that helps developers to write pre- and postcondition validations". The library supports a wide-variety of conditions (including those great string based IsNotNullOrEmpty). On the right is a screenshot of the condition validation extensions if you want a quick look.

The library provides a consist way to manage condition checking, and even provides a way to pass a formatted string for the exception message:
Condition.Requires(context, "id").IsNotNull("Parameter {0} cannot be a null reference");

Another feature that this library provides is the WithExceptionOnFailure (AlternativeExceptionCondition WithExceptionOnFailure() where TException : Exception) allowing you to define the exception to be raised when the condition fails. While this is not something you would generally want to do, the added flexibility is certainly appreciated.

.NET 4.0 Code Contracts

.NET Code Contracts is part of the 4.0 version of the .NET framework. From MSDN: "Code contracts provide a way to specify preconditions, postconditions, and object invariants in your code. Preconditions are requirements that must be met when entering a method or property. Postconditions describe expectations at the time the method or property code exits. Object invariants describe the expected state for a class that is in a good state."

It seems intuitive, and easy.

The downside? It requires your application run on .NET 4.0. If your already ugpraded, this seems like a great choice. I mean, it's built into the Framework (no external dependencies ++), and generally offers a comparable offering to other open-source implementations designed to provide this functionality.

Compared side-to-side with Conditions, the syntax and code appear very similar:

            Contract -> Contract.Requires(context != null, "Parameter context cannot be a null reference");
            Condition-> Condition.Requires(context, "context").IsNotNull("Parameter {0} cannot be a null reference");


It's slightly more flexible in it's implementation than Condition. Most notably because Condition has a default set of validations, and exceptions, and Contract is wide open.

As an additional bonus, Code Contracts offer Legacy Requires Statements. From their description it is:

Most code already contains some parameter validation in the form of if-then-throw code. The contract tools recognize if-then-throw statements as preconditions when the statements appear first inside a method, and the entire set of such statements is followed by an explicit Contract method call, such as a Requires, Ensures, EnsuresOnThrow, or EndContractBlock.
When if-then-throw statements appear in this form, the contract tools recognize them as legacy-require statements. The EndContractBlock form is used only if no other contracts follow the if-then-throw sequences, but they should still be tagged as legacy-requires.
Shrinkr's Check.Argument
Shrinkr is "a Url Shortening Service which demonstrates some of the best practices in developing real life web applications." and contains a fluent checking class structure. It's simple, clean and provides a way to validate arguments and provide predicable exception handling.

Here's an example of the Check class. I have also seen a version of this where the Check, Argument classes are not static (from another location):
public static class Check
{
    public static class Argument
    {
        public static void IsNotNull(object parameter, 
                                     string parameterName)
        { ... }

        public static void IsNotNullOrEmpty(string parameter, 
                                            string parameterName)
        { ... }

 .... etc ....
}
This provides the basic context that Conditions provides, but is a far simpler implementation. It's also more of a larger project and really out there as a stand-alone library. However, it does meet the goals above, and would be an easy addition to any enterprise's library.

End-Notes:
... I still like Conditions the best, but only slightly. Mostly it's the little things, like formatted messages (so I can extract it to a resource) or the validations already built and ready to go.

... There are plenty of options to choose from. Pick one and start using it. Almost all of these will produce better, more consistent results than role-your-own. If your code does not validate add this and get started.

... This is an easy upgrade to your library that will produce good results in the short, middle and long term.

Resources:
Shrinkr
CuttingEdge.Conditions
CuttingEdge.Conditions (NuGet)
NuGet
Fluent Validation
.NET 4.0 Code Contracts on MSDN Magazine
DevLabs Code Contracts
Fluent Validation
FluentValidation for .NET 2.0
GuardQ

Tuesday, January 17, 2012

Best Practices for a .NET Extension or Plug-In


These are best practices that I created for writing a .NET Extension or Plug-In so some of the references and nomenclature are .NET specific, but the principals and ideas can be extended to any programming language or application design.

Best Practices for Writing a Good Extension or Plug-In:
  1. Any extension should have logging features (and ideally support verbose, error, warning messages). Most applications provide some sort of logging capabilities you can use or extend. This is preferred to designing your own simply because you would have to monitor two sets of logs not to mention the additional configuration, and maintenance of adding a second logging mechanism. If you do have to add your own logging, try to leverage an existing logging infrastructure: log4net, Microsoft Enterprise Library.
  2. If possible avoid any additional (and most importantly external) database or service calls. Aside from the performance hit this can add, your introducing potentially volatile resources that will affect the host systems ability to work properly.
  3. Settle on a single purpose or function for your extension. Don't try to make it do several things, and work in several different functions. It's hard to understand, maintain, and a nightmare when 'something' inside the extension/plug in goes bad.
  4. Limit external dependencies. If at all possible you want your extension/plug-in to be entirely self-sufficient. Any information or exchange should be provided by the host system via a state bag, or in the direct actionable items available.
  5. Document as much of the plug-in as possible within the code module. Include references, and be explicit. You should always document, but people tend to forget about extensions and plug-ins. You write them, they get deployed, and then days, months, years later... doom. The more that's in the code when you open it back up the quicker you can fix it.
  6. Handle and dispatch exceptions in almost all cases. If you can't handle the exception, and it needs to be raised to the host system, then make sure your logging (see #1 on this list) records the exception with as much information as possible. In my experience a host system most often reports very little useful information or (as in one case I remember) it reports absolutely nothing.
  7. Design the functionality of the plug in! So many times, people try to write everything inline for a plug-in rather than following the same coding practices that they would in any other application or feature. 
  8. Favor robust naming if your plug-in and if possible the methods, functions, and variables within it. Often when dealing with a plug-in it needs to be self explanitory to the infastructure dude, the end-user, and in almost all cases other people.
    1. Here's a quick example: 
      1. MyCompanyNamePlugIn - SeriouslyThat does that do? 
      2. MyCompanyUpdateCreatedDateOnNewRecordPlugIn - Ok, really simple. Want to guess?
  9. Consider interprocess communication if execution is lengthy, intensive, or will impact the performance of the host system. If the action is lengthy or is going to impact the host system, then consider having your plug-in use a queue or call a service for executing the action. If performance is going to be impacted in an extreme negative, consider external executing with a service-bus or queuing system.
References:
Best Practices for Developing Your First Ektron Site
Best Practices in Plugin Development (WordCamp Seattle)

Resources:
log4net
Microsoft Enterprise Library.

Tuesday, January 3, 2012

Best Practices for Developing Your First Ektron Site

This is a good presentation on best practices for Ektron.

Key Points:

  • Prefer SmartForms over HTML content - SmartForms provide a structured representation of your content allowing for greater control, and options for content re-use.

  • PageBuilder - The presentation recommends leveraging PageBuilder. My own experiences with PageBuilder have been mixed, but then again I am working with 8.0 and not version 8.5

  • Create an abstraction layer of Ektron - A key point in any application, but most definitively within Ektron. An abstraction layer to avoid directly calling the Ektron assemblies.

  • Have a caching strategy

  • Logging - The presentation recommends using the integrated Microsoft Enterprise Library logging that is already used within Ekton CMS.

  • Configuration - The presentation points out that the Ektron configuration, and your custom configuration should be separated into different configuration files.



Presentation:
Best Practices for Developing Your First Ektron Site

Thursday, November 20, 2008

Exceptions

One of my pet peeves is a developer not implementing exception handling in a useful manner. Exception handling needs to be an important part of design and not just wrapping all your code in a try/catch block. This does nothing for me:

catch (Exception ex)
{
    [Do something]
}


even worse is this:

catch (Exception ex)
{
    [Do something]
    throw ex;
}


All this does is give away the full stack trace for any exception handling further up the chain.

A better pattern/design/practice for handling exceptions would be to actually handle any exceptions you're catching. That means catching specific exceptions like InvalidOperationException, ArgumentException , or even better, a custom, meaningful exception specific to the task instead of the base Exception.

Speaking of custom, if you're going to define your own exceptions, be sure to provide grammatically correct messages that will be meaningful to someone down the road. Also include the three common constructors that are implemented by all the system exceptions (No parameters, single string parameter, and string parameter and inner exception parameter).

When throwing exceptions, use care to choose the correct type instead of just throwing ApplicationException. Consider returning null for cases of extremely common errors instead of throwing an exception. And most importantly, don't use exceptions as part of normal program flow. Remember try/catch is analogous to a goto statement so don't abuse it.

Resources:
http://msdn.microsoft.com/en-us/library/seyhszts.aspx