CSC/ECE 517 Fall 2011/ch7 7d os

From Expertiza_Wiki
Jump to navigation Jump to search

Anti-patterns

What is an Anti-pattern

An anti-pattern describes a solution which is commonly used because at first it seems beneficial, but, in fact, it is an ineffective or bad solution. The anti-pattern is usually attractive to inexperienced programmers but as the complexity grows or context of a problem changes, the problems with the pattern become more obvious. The term “anti-pattern” was introduced in 1995 by Andrew Koenig in his book AntiPatterns, published shortly after the Gang of Four’s Design Patterns.

Benefits of Anti-patterns

The benefit of documenting anti-patterns is that they identify bad solutions and often can point out better solutions. An implemented anti-pattern does not reveal itself until the project grows more complex, so it saves time to be able to know and identify an anti-pattern early. Because many people have stumbled into the same anti-patterns, better design patterns for many anti-patterns are well-known.

A workflow for anti-patterns

A useful description of an anti-pattern contains both an indication of why it is a bad solution, and a way to refactor it into a good solution. <ref>[3] Sourcemaking </ref>


Because this class is concerned with Object Oriented programming, the focus of the next sections will be on several object oriented anti-patterns. There are dozens of known anti-patterns spanning all domains of software engineering, from management and organization practices to design issues to coding. For a more comprehensive list see Cunningham and Cunningham's AntiPattern Catalog.

Object-Oriented Anti-patterns

Anemic Domain Model

The Anemic Domain Model is an anti-pattern of creating objects which have little behavior aside from getter and setter functions. Rather than including object logic within the objects, the logic is implemented from a higher level. In other words, the methods that describe an object’s behavior are not implemented in the object’s class itself, but instead in a class or other piece of code that contains that object. <ref>[4] Anemic Domain Model | Martin Fowler</ref>

For example consider a BankAccount class that has getter and setter methods for interest and cash. Rather than including an accrueInterest method in the account itself, the account just contains getter and setter methods for interest and cash. The logic of calculating the interest and updating the cash is implemented in a higher level code, such as the Bank class, which contains BankAccounts. Instead of using object oriented programming advantageously, the BankAccount uses the extra overhead required for a full object without being more useful than a simple data structure or row in a database table.

BaseBean

The BaseBean anti-pattern describes a pattern where a utility object is subclassed. The seeming benefit is that the subclassed class can very simply use all the utility’s functionality. Utility objects like Java’s hashmap are not in the control of the developer, and if they change it . Also, inheritance take place when there is a meaningful “is-a” relationship, which is usually violated . The solution to this anti-pattern is to use composition and change it to a “has-a” relationship, as shown in the diagrams. <ref>[5] Wikipedia: BaseBean</ref>

BaseBean anti-pattern [1]
Refactored using composition [2]

Call super

The call super anti-pattern occurs when a method in a subclass must call the method it is overriding in the superclass. Everyone overriding a method with partial functionality has to remember to call super. It seems like a minor annoyance, but there is no reason to force this responsibility on the user of the API. <ref>[6] Call Super | Martin Fowler</ref> As an example, suppose there is a class mammal. The class has a method digest_food. Suppose all mammals digestive systems work the same way except in how they put food in their mouths. For example, humans use a fork and whales just swim around with their mouths open. Instead of detailing everything that happens in the digestion, subclassed mammals just specify how the first part, getting the food in the mouth.

 
  public class Mammal {
    public void digest() { 
      swallowFood() ...
    }

  }
. public class Human{
    public void digest() { 
      liftFork() ...
      super.digest() 
    }
  }
    

The best way to avoid super calls is to refactor the code using the template method pattern.<ref>[7] Wikipedia: Call super</ref> In our example, the anti-pattern in fixed as follows:

 
  public class Mammal {
    public void digest() { 
      putFoodInMouth()
      swallowFood() ... 
    }
    protected abstract void putFoodInMouth():
  }
. public class Human{
    protected abstract void putFoodInMouth() { 
      liftFork() ...
    }
  }
    

Circular dependency

Circular dependency is an anti-pattern in which two or more modules depend on each other to work properly. This can have many negative effects, including making it impossible to reuse a module without the other, making, and causing memory leaks with reference counting garbage collectors. <ref>[8] Wikipedia: Circular Dependency super</ref>

Circular dependency is a very broad anti-pattern so there is no one solution or cause. Sometimes the dependency is caused because an object must keep track of another. In this case the observer pattern is a good solution. Tools exist that help detect circular dependencies. <ref>[9] Wikipedia: Circular Dependency super</ref>

Object cesspool

An object pool is a design pattern in which some initialized objects are kept ready to use rather than allocated and destroyed as they are needed. This can be used for objects that would otherwise have to be created and destroyed often like session objects on a web server, saving computing time.[10]

The object cesspool is an anti-pattern in which the object pool is used improperly, and can result in costly bugs. The cesspool occurs when objects are not reset as they should be after being used. The next time an object is used it may contain state information from the previous instance which should have been reset. This can cause bugs or security issues. Using the the sessions example, if an object pool is used to track sessions and a user logs out, the users details should be completely reset. If they aren't and another session is loaded on that session object when another user logs in, the new user may be able to see private information of the other user such as their login information. [11]

Yo-yo problem

The yo-yo problem is an anti-pattern in which the inheritance hierarchy becomes so deep that the programmer has to constantly switch back and forth between subclasses and superclasses to understand the program.<ref>[12] The Mutable Compendium of Object Oriented Wisdom:Yo-yo problem</ref> This quickly reduces the effectiveness of the programmer. The key to avoiding this is to limit the depth of hierarchy as much as possible and to improve the documentation of classes so that documentation of the lower classes also contains the information the user of that class needs to know about their superclasses.

References

<references/>