The Anti Patterns Misconception

I kicked off this Software Patterns category with A Brief Introduction to Software Patterns. The following is a short quote from that post which sums up, in a nutshell, what that post had to say:

A pattern is basically a capturing of a problem (in context) together with a solution to that problem

Another pattern related term that is in common use in software development is “anti-pattern”. The concept of the anti-pattern is something of a misconception, so here I’d like to take a look at why it’s a misconception.

It is very convenient to talk about “good” and “bad” practices, but this is problematic in itself because it oversimplifies the world far too much! Please take the following points into account:

  • One of the important things a pattern captures is the context in which a problem is occurring, and hence the context in which the solution is applied
  • In addition, a pattern also captures the tradeoffs accepted in applying the solution

What constitutes “good” and “bad” practice depends largely on what one is trying to do in the first place, and on the surrounding circumstances. Further, a solution which is a good one subject to certain context/tradeoffs might be a bad one subject to different context/tradeoffs.

The anti-pattern misconception starts with another misconception - that a pattern captures a best practice solution to a problem in context, which is not correct. Certainly many known patterns do capture best practice solutions, but the best practice part of it is not part of the definition of what a pattern is. It just so happens that what people are usually interested in is the best way to do things, and hence enthusiasts have documented many patterns capturing best practice solutions.

Just suppose for a minute that the commonly believed myth about patterns capturing best practice was true. That leaves a reason - a need in fact - to capture wrong/bad/worst practices, to help developers recognise them and understand why they are wrong/bad. This is where the term anti-pattern comes in. In reality anti-patterns are just patterns - that is, patterns in which the solution captured is a bad one. In fact, the anti-pattern captures a solution that does not satisfy the acceptable tradeoffs, does not work in the context, or both. A pattern captures a solution to a problem - be it a good, bad, or indifferent one, hence the anti-pattern concept is actually meaningless. Unfortunately, in my experience, write-ups and discussions of anti-patterns either do not take into account that the world is not so clear cut, just choose to ignore it, or both.

Double Dispatch Pattern

The Double Dispatch pattern is a design pattern used to leave a class hierarchy open to having extra operations added to it. Further, double dispatch allows the implementations of such added operations to be different according to the actual, or “concrete”, type of the class.

In this article I will start with an example of C# double dispatch. Although the example uses C# as its language, both Java double dispatch and C++ double dispatch could be implemented in a very similar way.

Example

Consider a drawing program (yes I know you’ve heard this one a thousand times before, but it serves well as an example!). This program will have a shape class hierarchy that will be headed up by an interface called IShape. Let’s say we have two concrete classes: Circle and Rectangle.

The role of the shape hierarchy is to encapsulate information about the properties of the shapes in our drawing program, such as their positions and sizes. That is to say, its role is to contain application logic, and it does not want to have code in it that interacts with the GUI. In typical GUI tradition, we will want to put up dialog boxes for each shape to allow the user to update its properties, and this dialog box will be different depending on whether the IShape object is a Rectangle or Circle. Here is a fragment (in C#) of the shape hierarchy:

    interface IShape
    {
        ...

        void move(int newX, int newY);

        ...

        void process(IProperties props);
    }

    class Circle : IShape
    {
        ...

        void IShape.move(int newX, int newY) { ... }

        ...

        void IShape.process(IProperties props)
        {
            props.show(this);
        }
    }

    class Rectangle : IShape
    {
        ...

        void IShape.move(int newX, int newY) { ... }

        ...

        void IShape.process(IProperties props)
        {
            props.show(this);
        }
    }

I have left in the move() method simply to give the hierarchy some sense of realism, but process() is the method we’re really interested in here. Code that uses our shape hierarchy will only be doing so through references to IShape. However, when methods are called, the methods invoked are those of the concrete classes - therefore, in method calls the actual concrete class is known.

Further, in the implementation of process() in a concrete class, the this reference has the type of the concrete class - this allows us to take advantage of overloading.

This brings me to the classes that will actually display the properties dialogs - i.e. the classes that will actually contain the GUI code. They will be headed up by an interface that I am going to call IProperties, and that looks like this:

    interface IProperties
    {
        void show(IShape s);
        void show(Circle c);
        void show(Rectangle r);
    }

IProperties declares a show() method overload for each class in the IShape hierarchy. Because (in the implementation of the process() method) this refers to the concrete class of the object in the IShape hierarchy, the correct overload of IProperties.show() will be called.

If the IProperties interface has only one implementation - i.e. presumably called Properties - then it is possible to get away without the interface. However, this is something I do not recommend as it makes IShape and its subclasses just a little to tightly coupled to its properties for comfort. Further, IProperties may have more than one concrete class. For example, imagine that our drawing program is quite sophisticated and can distinguish between regular users and administrator level users. Let’s say that administrators have extra properties available to them. This would require more than one implementation of IProperties - say, UserProperties and AdminProperties. Then all that is needed is for an instance of the correct concrete properties class to be passed to IShape.show(). To keep the article’s size down a bit, I haven’t shown any of the code for IProperties‘ concrete classes, but I assume readers will have no problem mentally filling these in.

Now, the following example code shows how an IShape object’s properties can be invoked:

    void example(IShape sh, IProperties props)
    {
        sh.process(props);
    }

The Double Dispatch Pattern

So far I’ve just given a code example - now to show double dispatch as a pattern. I’m going to do this using a very simple description.

  • We are doing object oriented software development using a language such as C#/Java/C++. We want to add methods to a class hierarchy [the shape hierarchy], but (a) we want to keep code for these operations decoupled from the hierarchy and/or (b) we want to avoid modification of the hierarchy’s own code. Further, we want these operations to be polymorphic - that is to say, we want each concrete (derived) class in the hierarchy to have its own implementation of the method servicing the operation.
  • Therefore… First, invoke the operation on an object in the hierarchy [that is, via the process() method, in the example], and let the object (which knows what its own concrete class is) forward the operation on to another “handler” object containing the method that services the operation [the IProperties object that has the show() method]. This solves the problem but at the expense of having more class hierarchies to manage and maintain. Also, if a class is added to the original hierarchy, then each handler object class will need a method adding to it

This is a standalone write-up of the double dispatch pattern - as opposed to the informal illustration given by the above example. In passing, I hope to add further examples in the (near) future.

Finally

While I’ve seen a few examples of the double dispatch pattern in text books, I haven’t seen any literature describing it as such, that is, as a pattern (but note I’m saying I haven’t seen any, not that there aren’t any). Normally, double dispatch is mentioned as a technique used within the Visitor pattern, a more specific design pattern (see Gamma et al - the “Gang of Four Book”, mentioned in my previous article A Brief Introduction to Software Patterns). In fact I think developers often confuse the Double Dispatch pattern with the Visitor pattern. I think that is a shame, and that the former needs to be understood in its own right.

A Brief Introduction to Software Patterns

I’m pretty sure that the first contact most software developers at large have with patterns is through the well known book "Design Patterns: Elements of Reusable Object-Oriented Software" by Erich Gamma, Richard Helm, Ralph Johnson  and John Vlissides - the "Gang of Four" (GoF) as they became known. This book - containing twenty-four object oriented design level patterns - is just one of many books on the subject, and the twenty-four patterns it describes are just a small number of the documented patterns that are out there. Further, the patterns it describes are all pitched at the level of object oriented design, whereas there are many patterns documented at all stages and levels of software development: for example, see "Pattern-oriented Software Architecture Volume 1: A System of Patterns" by Frank Buschmann, Regine Meunier, Hans Rohnert, and Peter Sommerlad, which looks at patterns for system architecture, design patterns and programming idioms.

In order to start off the Software Patterns category, I thought I’d write a short introduction to the topic. In it, I aim to give an "in a nutshell" explanation of both what a pattern is, and what patterns contribute to software development.

What is a Pattern?

A pattern is basically a capturing of a problem (in context) together with a solution to that problem. As so often happens, though, things are just not that simple. To understand what a pattern is, I think it is worth stepping back and looking more generally at problems and their solutions. With this in mind, consider the following:

  • There is very rarely any such thing as the solution to a problem. That is to say, any problem will usually have more than one solution, each solution offering its own set of tradeoffs. Finding a solution is not a matter of finding the right solution, rather it is a case of deciding on the most acceptable set of tradeoffs.
  • Deploying a solution to a problem entails risk. If the solution turns out to be the wrong one, resources have been wasted. This risk can be mitigated by understanding the tradeoffs a solution offers, and the tradeoffs are best understood by drawing on the available experience.

The purpose of capturing a solution as a pattern is to help users choose the solution that will work best in their particular situation. Therefore, the most useful patterns are those harvested from existing practice/experience.

A pattern is made up - be it explicitly or implicitly - of the following elements:

  1. Name. The name by which the pattern is known. This may also give alternative names, if there are any
  2. Context. Problems occurs in context, and the context influences the suitability of a solution
  3. Problem. Self explanatory. This is usually quite a short statement, and a popular choice is to phrase it as a short question
  4. Forces. Factors that limit the choice of solution. The term forces is a metaphor from physics (forces influence the direction of the solution)
  5. Solution. Self explanatory
  6. Consequences. The pros and cons associated with the choice of solution. Sometimes the more general term Resulting Context (emphasising that the solution/consequences have changed the context from that in which the problem occurred) is used instead of consequences

These are the essential elements, but they are non-limiting in that they may be supported with other material. In particular, a pattern write-up often begins with an abstract or overview of the pattern, and of course examples are always good to include. Also, very importantly, examples of known uses should be included.

Example Pattern

  • Name: Proxy
  • Context: An object oriented software development where access to an object (the Subject) is non-trivial, in that it is necessary to assert some control over such access, or intercept the access in some way. For example, we may need to insert code to write log entries when operations are invoked on the object
  • Problem: How can control be asserted over access to the Subject?
  • Forces: The control asserted must be transparent from the client code perspective
  • Solution: Let client code address a representative of - that is, a Proxy for - the Subject. The client code addresses the Proxy, and the Proxy forwards requests to the Subject (as well as forwarding the Subject’s responses to the client). In order to address the transparency requirement, the Proxy object should have the same interface as its target object; ideally it should be possible to interchange the Subject and Proxy in the client code
  • Consequences: The above solution implements the ability to transparently assert control over access to the Subject. However, this transparency also hides any extra work done to access the Subject from clients. Therefore, it must be kept in mind that their is potential for performance problems to subtly creep into the system

Notation

There are various approaches to writing up patterns. The above example is also an example of the most disciplined. However, this approach does suffer from being quite formal and not particularly accessible for the reader. This is probably why pattern authors generally have a leaning towards less formal notations. Two popular forms are:

  • Simply stating the pattern as a problem/solution pair. In this case, usually the context and forces are rolled in with the problem, while the consequences are included in the solution
  • Describing the pattern from the perspective of intent and motivation. This is the approach used in the popular GoF "Design Patterns" book alluded to above in the introduction

Finally

I think patterns are a very important tool in the software development toolbox. I also think that the tendency towards more relaxed notational styles is a good thing in general because it makes for easier and more accessible reading. However, the more relaxed styles make it easy to overlook a fundamental point: a pattern is motivated by the need to understand the solution to a problem, together with its consequences. This must be kept in mind, otherwise there is a risk of this particular tool loosing its value.

The Difference Between Encapsulation and Abstraction

The difference between encapsulation and abstraction seems to trouble some people, which is something I find rather odd. While both are concepts important to object oriented design, and while both are complementary to one another, they are two different concepts. In this article I will explain briefly what encapsulation and abstraction are, and how they interact with, and complement, each other.

First, a few words about each of abstraction and encapsulation:

  • The use of abstraction in software design is similar to its use in maths. It involves representing a physical thing or a concept in terms of its essential properties and behaviour. This way, such a thing, be it a concept or something that has physical existence, can be dealt with in a way suitable for modelling the way the real world behaves.
  • Encapsulation is a tool - that is, a tool in the intellectual sense - for drawing boundaries around implementations. One reason for this is to allow implementations to change without affecting the outside world. Another reason, perhaps more important, is its usefulness in structuring the design of a system. To further emphasise the organisational usefulness of encapsulation, consider that it allows the implementation to be tested in isolation, without integration with the rest of the system. A simple function is one example of a unit of encapsulation - that is, as long as it does not use any global variables or any other kind of globally accessible resource. In passing note that this is why global variables are such a bad idea - they compromise the boundaries of encapsulation.

In my articles Accessing Object Properties While Respecting Encapsulation and Updating Object Properties While Respecting Encapsulation, I used a Circle class to illustrate the querying and updating of object properties. The class implements a Circle abstraction, in that Circle is manifested in a computer model by being represented as a combination of state and behaviour. Encapsulation is the instrument that permits the Circle to expose its state to the outside world in a way that keeps the public perception of its state separate from the way its state is implemented. For example, the Circle exposes a public radius property, but the implementation could be in terms of the diameter - requiring a calculation in the background when the radius is queried.

Abstraction and encapsulation are each complex topics in their own right, far more so than might be apparent when these concepts are first encountered. I hope this short article has helped to shed some light on the difference between encapsulation and abstraction.

Technical Debt

In this article I want to talk about a term that I think is just brilliant: technical debt! The term technical debt makes an analogy: it considers the use of quick, but poor, technical solutions to store up a form of debt. As with more conventional forms of debt, the immediate problem is solved, but trouble can be stored up for the future. The reason I like the term so much is because, by its use of analogy, it makes it much easier to communicate a concept that is, otherwise, rather tricky to explain.

All too frequently in software development, technical/design problems are solved sub-optimally in the interests of speed. Actually that is putting it too nicely. Such problems are often solved using quick and dirty hacks. This is usually done in the belief that it will get a solution in place quickly. Often the belief is actually correct, and this approach does indeed get a solution in place quickly. However, there is a price to be paid. The price manifests itself in the form of code being difficult to work with in the future, and therefore the risk to future deliveries is much increased.

Here lies the importance of the debt analogy: there is nothing wrong in principle with technical debt, but like any other kind of debt it must be managed, and it must be managed effectively. If debt is to be entered into then it is imperative that the debtor is in control of the debt - the debt must not be allowed to control the debtor!

The need to make a delivery in time, typically so as not to miss a market window, may make it necessary to accept a "quick hack" solution. However, such a solution can not be allowed to remain in place; if it is, then soon it will become difficult - and even practically impossible - to meet deadlines. For this reason, some planning is necessary; time must be made factored into the development schedule for solutions carrying such a technical debt to be reworked with more enduring solutions. Failure to do this leads to developers being unable to work with the code base, and ultimately the code base needing to be rewritten from scratch.

Typically, such rework is not carried out because (non-technical) management decide to spend the development time on new features - after all, the code works so why spend time rewriting any of it? Software developers then become frustrated because they perceive this as incompetence on the part of their management. This attitude is wrong on the part of developers! Technical debt is in the technical domain, and therefore it is not something non-technical management should be expected to understand - at least, not without it being explained to them in such a way that they, as non-technical people, can understand it. The responsibility here lies with the senior software developers, who have a responsibility do learn to communicate this issue to their management.

?>milf soup Carmen De Luz Tori Black ballhoneys round asses assparade Dylan Ryder bang bus big mouthfuls Newbie Black nice tits Bait Bus Gina Lynn Evie Delatosso fucking teen Bianca Dagger Brittney Banxxx fuckteamfive Jenaveve Jolie Tug Job milf soup Alexis Silver Riley Mason Brooke Lee Adams ball honeys Black Sonja ass parade Andi Anderson Miley Ann Esperanza Gomez Backroom milf bigmouthfuls Brianna Beach bangbros Dirty World Tour Fuck Team Five Abby Skyy Barbie Banx Alexa Bold milflessons Bailey Brooks milflessons Tugjobs Paola Rey milf lessons bang bros Ahryan Astyn Beauty Dior big mouthfuls facialfest Allie Perdue workinglatinas Alexis Amore ass parade Savannah Stern Rebeca Linares Eva Angelina Alicia Silverjones fucking girls Tanner Mayes Fuck Team Five bigtitsroundasses Missy Woods Alanna Ackerman Brianna Love bangbus couple pussies fucking pussies Alexa Benson Monstersofcock Allie Foster Bobbi Starr fuck team five workinglatinas bang bros fuck videos Bait Bus ass parade Alicia Tease bangbros ball honeys big mouthfuls BIG booty 3DS Max 8 OEM3Q 3GP Video Converterdownload acdsee manager 2009 oemred eye remover pro 1.2cheapest windows vistacheapest windows vista ultimatecheap AutoCAD 2009Vision Backup Enterprisecheap Macromedia ColdFusionnero photoshow 5 downloadadobe photoshop cs oemcoldfusion mx 7 downloadkamagra sildenafil citratekamagra generic viagraorder caverta onlinecaverta 100buy cavertatadaliscasodex 50 mg tablet