Patterns and Principles (Part I) - Getting Started

by Rasmus Kromann-Larsen October 24, 2008 15:54

Introduction

Design patterns and principles are a fundamental thing in software development. Yet they're can be quite elusive and difficult to get into. As one of my goals with this blog is to further my own knowledge, as well as share it with others, I've wanted to do posts on basic object oriented principles and patterns. I believe that patterns is one of those things you grasp best when actively thinking about them - and thus to improve my own skillset on patterns, writing blog posts and thinking up good examples is a great way to go.

While this post is mostly an introduction to the series, my approach will definitely be a pragmatic one. I'm aiming to have two types of posts in this series, basic posts introducing specific design patterns or principle with up-to-date .NET examples and more advanced posts on the variations of the patterns and my own crazy experimentation with them. In any case, both types of posts should be brimming with examples if all goes as planned.

Design Principles

Drops of distilled wisdom and experience. Most of these principles deal with increasing maintainability, testability, flexibility, reducing (unneeded) complexity and attaining high cohesion and low coupling. Allowing you to mitigate at least one of the inevitable three (death, taxes and changing requirements).

I personally see them as guidelines for thought, not golden rules, you might encounter situations where fewer of these principles may apply, as there's often trade-offs involved. However, keeping them in mind is a way to open your eyes to other solutions. In my experience, some of them are easier to be adamant about (DRY springs to mind), while some are more subjective considerations and best practices. I guess my point is that you should avoid following anything blindly without thought. Broaden your horizon, don't narrow it.

I'll not dig too deep into these, but rather give a short introduction in this.. uh, introduction post. Note that this is not an exhaustive list.

  • Single Responsibility Principle
    • Separation of Concerns. An object should have one and only one reason to change, thus increasing cohesion and avoiding coupled responsibilities. It ties into many of the other principles.
  • Open/Closed Principle
    • Your software entities should be closed for modification, but open for extension. Hard to explain briefly, but the gist is to be able to extend the system without modifying existing code (save for bugs). Examples could be: Avoiding dependencies on internal workings and down-casts to specific types.
  • The Interface Segregation Principle
    • Do cohesive, responsibility-based interfaces (think roles) instead of huge general interfaces. Your clients will then only depend on a minimal subset of your methods, instead of potentially depending on methods they're not using.
  • DRY
    • Don't Repeat Yourself. Duplication is bad, mkay? A good example of this is duplicate code, you'll always miss at least one spot when making changes later.
  • Dependency Inversion Principle
    • "High level modules should not depend upon low level modules. Both should depend upon abstractions.". Seeks to lower coupling in the system and increase testability. Applied through dependency injection and often IoC (Inversion of Control) containers.
  • Liskov Substitution Principle
    • Informally: When defining an interface or contract, the system should be able to use any (correct) implementation of it. That is, clients of the contract should not have to know the implementation details (or depend on them). Ties into Design by Contract.
  • Law of Demeter
    • Also known as the Principle of Least Knowledge. Don't talk to strangers. The law states that a method on an object should only call methods on itself, parameters passed in to the method, objects it created and composite objects. This means don't go dot, dot, doting yourself into the entire object tree.
  • Tell, Don't Ask
    • Aim to tell objects what to do instead of asking it about it's state and deciding what to do. The idea is that the object probably knows better than you. It also forces you to think about responsibilities.
  • YAGNI
    • You Aren't Gonna Need It. From Extreme Programming. Don't waste your time adding functionality based on what you think the future might bring. You will (most likely) be wrong. In addition, you will have to maintain this extra code and complexity. Variation of KISS (Keep It Simple, Stupid).
  • Favor Composition Over Inheritance
    • Inheritance is often over- and misused. Inheritance is an 'is-a relation' and is often used as a 'has-a relation' (composition). An advantage of composition is that composed objects can be replaced dynamically - and they can vary independently. Inheritance still has it's place in some cases though (Hint: When you have an 'is-a relation').

Design Patterns

Design patterns are reusable solutions to recurring problems in software development. One of the best points about design patterns is that they allow developers to talk on a higher level, since they have a shared vocabulary of design techniques. Seeing pattern names in code can also communicate an intent that can otherwise be hard to see.

A lot of the same things from the design principles section apply here too. An UML diagram describing a design pattern is just one instance of the pattern - they're meant for inspiration and almost all patterns have several variation points.

I'll not even try to list design patterns yet, they come in all shapes and sizes, better save something for next time.

Literature

While blog posts and other online sources are good for quick answers, nothing beats sitting down with a well-written book on a subject.

 

Design Patterns: Elements of Reusable Object-Oriented Software

Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides

If you've read anything about patterns, you will undoubtedly have heard of the GoF (Gang of Four) book, the often proclaimed Bible of Design Patterns. While this is a great book, especially as a reference catalogue of patterns when you want to look something up, I was kind of lost when I read it the first time. The book is rather abstract and it can be rather confusing for someone starting out with design patterns. I really think you should make it part of your book collection, but if you're starting out with patterns, I would recommend starting out with this book instead:

Design Patterns Explained: A New Perspective on Object-Oriented Design

Alan Shalloway, James Trott

This book was my personal eye-opener. It is somewhat more chatty than the GoF book, slightly less catalogue, slightly more "getting into object-oriented design". It's a great introduction to design patterns and the authors go to great lengths to not only describe the patterns, but to discover them by examining different solutions and quantifying the strengths and weaknesses. This is a great book for bridging the gap before GoF.

 

Refactoring: Improving the Design of Existing Code

Martin Fowler

While refactoring is not design patterns per se, refactoring is a method to mold your code (or others code) towards some of the same goals as the ones presented by design patterns. It's all about improving the maintainability and flexibility of your software. Fowler does a fine job of explaining the reasons for the different refactorings, describing code smells and which tools to use to get rid of them. Another reason knowledge about refactoring is good is that often, you won't have the luxury (or curse) of working solely with your own code. Refactoring can be a great tool to unravel spaghetti code and gaining insight while (hopefully) adding tests to support it.

Online Resources

If you want to get started reading more about patterns and principles, here's a few good links for getting started.

Conclusion

In this post, the first in a series of N, I gave a short introduction to design patterns and principles. I've outlined some recommended getting-started literature and hope to have sparked your interest. Next part will be a basic post describing the first pattern.

Note: I could have more sources in this post, but most of this post is tidbits from experience, opinion and a compilation of snippets from way too many sources. I'll list them in following posts, when we dig into the detail.

kick it on DotNetKicks.com

Tags: , ,

Development | Design Patterns

Embedded Scripting Language? Boo!

by Rasmus Kromann-Larsen October 07, 2008 21:59

 

Setting the stage

In a recent project, I've had the need to use an embedded scripting language. The main purpose was to give the end user a DSL like feeling, while retaining the power of a full-fledged scripting language. For a long time the project has been using IronPython to provide this, but recently I've run into a few problems and started searching for something new.

Problems with IronPython

One of the strategies I've used is to have functions that return functions to provide a more humane syntax, like so:

def TextWidth(width):
  def f(xq, xs):
    xs.SetTextWidth(width)
  return f

 

The idea here is that the users script will create a function that will be called later in the correct context and have the inner function take other arguments. However, it does make the script files more verbose and it can be hard to read the functions when they get more complex. Also it's very hard to add extra arguments to a given script context, since you have to find all the functions called in this context and add the argument to the inner function.

Lately, I've been finding myself leaning more in the direction of Ayende's anonymous base class approach. Basically, what you do is to provide a class that wraps the end user script and provides the scope of functions that can be called from the script. However, Python's class mechanics lend themselves very badly to this method, because Python requires abundant amounts of self keywords.

Another idea I had using the anonymous base class approach was to separate the actual scripting logic from the API using the bridge pattern. In pseudo-Python, it'd look something like this:

def TextWidth(width):
  impl.SetTextWidth(width)

 

I will probably write another post about this, but the main idea is to be able to swap the implementation of the script logic on runtime. One use of this could be to find more errors when new scripts are entered, by using a script logic implementation that performs extra validation on the arguments instead of actually performing the intended actions.

Enter Boo

I've had my eye on Boo for quite a while. It's an object oriented statically typed programming language that looks a lot like Python, written on the .NET framework. It's open source and was created in 2003 by Rodrigo B. De Oliveira. The really cool thing about Boo is the focus on extensibility. It's rather easy to insert extra steps into the Boo compiler if you want your own special macros or syntax.

So I grabbed the latest stable bits from Boo distributions (version 8.2), started up a new VS project and added a reference to Boo.

Compiler or Interpreter?

As mentioned in Arron Washington tutorial on Boo as a scripting language, it's possible to either use the Boo compiler or the interactive interpreter. I went with the compiler. I don't have intimate knowledge of the differences between Boos compiler and interpreter, but usual trade-offs include things like speed, since you're running compiled code instead of traversing some form of the abstract syntax tree.

One thing to keep in mind when using the compiler is that you can't unload the assemblies you create unless you unload the entire AppDomain. So unless you worry about AppDomain boundaries and have criteria for unloading your script AppDomain, memory usage will increase as you continue to compile different things. This problem is beyond the scope of this post, but Google is your friend. As my application is an ASP.NET application that usually gets recycled rather often and because my scripts are semi-static, I've decided not to dig deeper into this. Maybe if circumstances change.

Simple Example

As a simple example, the below snippet will load up the Boo compiler, compile a simple script where I inject some code into a class and call the method via the C# interface.

 

namespace BooConsoleApp
{
    public interface IRunnable
    {
        void Run();
    }

    public class Program
    {
        public static IRunnable CompileToRunnable(string source)
        {
            // Boo class we're injecting our code into
            // A simple Test class implementing our IRunnable interface
            var classDef = String.Format(
@"import BooConsoleApp
class Test(IRunnable):
  def Run(): 
    {0}", source);

            var booCompiler = new BooCompiler();
            // Compile to memory
            booCompiler.Parameters.Pipeline = new CompileToMemory();
            // Compile as library to avoid missing 'No entry point' error
            booCompiler.Parameters.OutputType = CompilerOutputType.Library;
            // Add our Boo code as input
            booCompiler.Parameters.Input.Add(new StringInput("test", classDef));

            // Compile the code
            CompilerContext context = booCompiler.Run();

            // Very basic compile error handling
            if (context.Errors.Count > 0)
                throw new Exception(context.Errors.ToString(true));

            // Create the actual instance of our IRunnable
            var runnable = context.GeneratedAssembly.CreateInstance("Test") as IRunnable;

            return runnable;
        }

        public static void Main(string[] args)
        {
            // Compile our hello world
            IRunnable runnable = CompileToRunnable("print 'hello world'");
            // Run the program
            runnable.Run();
            Console.ReadLine();
        }
    }
}

 

And the output is as expected:

image

Conclusion

In this post I gave a short primer on getting started with Boo as embedded scripting language. I hope to follow up with more advanced topics. Good luck on getting started with Boo until then.

kick it on DotNetKicks.com

Tags: , , ,

Boo | Development | IronPython

Powered by BlogEngine.NET 1.6.1.0
Theme by Mads Kristensen | Modified by Mooglegiant | Adjusted by Rasmus Kromann-Larsen

About Me

I am a danish .NET developer blogging about the technical side of my life, mostly .NET stuff, but also fundamental topics like design patterns, principles and productivity boosters.

In addition, I am a core group member of Aarhus .NET User Group.