Design Patterns in VB.NET - Terms to Know
 
Published: 12 Jul 2006
Unedited - Community Contributed
Abstract
This article looks at terms used in the GoF book which you should know well before reading the GoF book. It also looks at the terms I coined for certain concepts discussed in the tutorial.
by David Simmonds
Feedback
Average Rating: 
Views (Total / Last 10 Days): 21612/ 30

 

Introduction

There are several terms you should know before preceding.  Some are from the GoF book and there are a few terms I made up.  I am sure if I had taken the time to read lots of O-O books, I would have probably come across the proper and accepted terms.  Forgive me.

 

Terms used in the GoF Book

Interface Inheritance versus Implementation Inheritance

In the first case, we are referring to a class inheriting from an interface (or in VB terms, implementing the interface).  In the second case, we mean a class inheriting from a super-class.

 

Classes having knowledge of other classes

When one class knows about another class, it simply means that it holds a reference to the other class and its methods and properties.

Let us look at it from another angle.  When coding a class which knows another class, you have to know exactly which class it will need to use, the name of the class, etc.  You may also need to know its internal workings.  Obviously, it translates into higher coupling since a change to the referred class can mean a change the referee class.

 

Wide Interfaces

When a class interacts with, accesses and/or modifies another class through a wide interface, it means that it has intimacy with that other class.  It means that the "interactor" has wide knowledge of the "interactee" and is able to get its work done through that wide knowledge.  A wide interface means that the class knows all the methods and member variables which are available in order to manipulate them intimately.  We see this type of interaction between director and concrete-builder in the Builder-pattern.

Obviously, this not only breaks encapsulation, but it also greatly increases coupling.  It is somewhat similar to the wife who knows every little detail about the husband and how he thinks.  She knows just the right words to say and the little looks to drop to get him to do something.  She is interacting through a wide interface since she can reach across a wide set of psychological handles that affect his behaviour and the action she desires.  She knows the exact way to angle her face, remove a lock of hair and crease her lips to stimulate just the right part of the man’s psyche into action.  I do not say this is a bad thing; in fact, it is very necessary.  Men are lazy and need pushing and prodding.  It is simply an example of a wide interface.

Interaction through a wide interface makes for stability in marriage since a wife and husband are the hardest people to replace, their interactions being so complex, multi-faceted and fine-tuned. In the average circumstances, it gives children a stable environment in which to grow up and enjoy the input of both parties in their development.  So in fact, society benefits from the fact that wives interact with their husbands through wide interfaces.

 

Narrow Interfaces

A narrow interface is the interface through which most classes would normally interact with another class.  It normally consists of the interaction with properties and methods in a way that assumes a minimum of knowledge about the class, possibly just a single method name to invoke.

 

Aggregation versus acquaintance

Do not fall into the trap that I did when I confused aggregation with the use of a data-structure which contains several references to the aggregatee.  Aggregation has nothing to do with numbers and may involve one aggregatee or many.  So it may in fact be through a data-structure, but more times than not through a single object reference.

So what is it?  Aggregation means that the aggregator and aggregatee are bound in such a way that the useful object lifetime of the aggregatee is also the useful lifetime of the aggregator.  For as long as the aggregator has useful work to do, it needs the aggregatee to do so.

So think object lifetime and not numbers.  Due to the link between their useful lifetimes, it becomes useful for the aggregator’s constructor method to include the instantiation of a new aggregatee-helper class at the same time.  The destructor of the helper class is also tied to that of the main class.

For on-line browsing the web-browser needs to have a reference to a live internet connection and so the browser aggregates the internet-connection. Therefore we see the aggregator/aggregatee principle in the web browsers’ connection settings where the activation of the browser can be tied to the activation of the connection in the settings below.

Listing 1: Internet Options showing aggregator principle

 

 

Launching Internet explorer (in the absence of a network internet connection) automatically brings up the following.

 

Listing 2: Web browser instantiating a connection

 

 

 

Similarly, when there is no web browser to send useful work through the internet connection, there is no point in keeping it alive and we can configure dial-up connections to reflect this with the following dialog.  We configure the connection to be disposed of with the browser by setting the number of minutes we should allow the connection to be idle before disconnecting it.

 

Listing 3: Disposing connections when the browser shuts down

 

 

 

In the Builder pattern we can see a director as the aggregator and the concrete-builder as the aggregatee.

 

Acquaintanceship

Acquaintanceship is when there is a reference to an acquaintance class.  However, the usefulness of the main class is not tied to the usefulness of the acquaintance.  It used to be that someone’s heart dictated the number of years they could live.  If your ticker gave up, you were forced to do the same.  Thankfully, this is not so anymore. Your heart is now a helper object, not the main object.  You are the one with the relationship to your kids, spouse, co-workers, community, clubs, country and God.  Your heart is here to help you to keep on living; you are not here to live just because your heart decides to continue beating.

Medical science recognizes this and has made dramatic and far reaching progress in cardiac medicine.   We have valve replacement, bypasses, pace-makers and, in the most extreme circumstances, heart transplants.  All these techniques mean that you now have an (albeit very strong) acquaintance with your heart.  Their lifetimes are no longer inextricably linked in an aggregator/aggregatee relationship.

Acquaintance is more typical in the bridge pattern.

 

Factory-Classes

In the creational patterns, factory classes perform instantiation services (return new product classes) on behalf of client code.  They make the decision about which class should be instantiated based on the needs communicated by the client code.  This allows clients to focus on the main work they are supposed to perform without worrying about how to procure the tool-classes they need.  In the same way you do not want to go to work everyday and worry about how they supply drinking water, clean air and office supplies at your office, the factory classes free and decouple the main classes from the tedium of instantiating other classes.

 

Product-Classes

The classes which are instantiated by factory classes and returned to the client are called product-classes.  They are usually returned not as an instance of the class they are defined as, but as the interface they implement.  This ensures that they are interchangeable and, regardless of the actual product class returned, it works seamlessly with the client.

 

Terms I Coined

We will see two types of interfaces: governing and interacting.

Governing Interfaces

Governing means that the interface outlines a set of methods which the inherited class must implement.  Certain functionality is guaranteed in those classes which implement it.  Everyone is fairly familiar with this concept.

 

Interacting Interfaces

Interacting interfaces are those which allow interchangeability of the classes which implement their signature.  Instead of interacting directly with the product classes which implement the interface, we interact with the interface.  The client will call a factory method which returns a product-class, but because the product is wrapped in the interacting-interfaces, we can interact with the product class through the interface instead of directly.

We see this in the workplace.  When the software engineer needs new tables added to the database, she does not send a request to “David.”  Instead, she sends a request to the DBA.  DBA is the interacting interface and when “David” leaves the job, the HR Manager will replace him.  So the Software Engineer will send the same requests to the new DBA, regardless of who is acting in that position.

It not only saves us from having to have knowledge of the classes with which we interact, but also the individual names of methods we need to call.  All of that is standardized through the interacting interface.

It is obvious that interacting interfaces subsume governing interfaces.  For one thing, there is no interface that does not govern the classes which implements it.  So then, all interfaces are governing interfaces.  The second reason is that for the client to interact with the product class as the interface, it must be governing the behaviour of the product class to ensure that the client has a uniform set of methods which can be invoked, regardless of the concrete-class hiding behind the interface.

 

Containable Object Groups (COGs)

As an aside, we have a famous expression in Jamaica, about being given a “basket to carry water.”  It literally means that you were given the wrong tools to do the job and you are generally ill-equipped to perform what needs to be done.  The literal translation is that “if you want to transport water, you need the right container to carry it in.”

We have a similar situation in object oriented design, but we are not as interested in the transportation mechanism as we are in what is being transported.  As a corollary to the saying, we could quip, “Before you carry water in a basket, make it into ice first.”  This water is more easily transportable.

Now to realize the full intent of object oriented programming and design patterns, let us fine-tune the analogy a bit.  When you are serving drinks to guests, you do not want to be breaking ice to put into every glass you pour.  So you use an ice tray.  Let us say you have an ice tray with 2 cube-holders.  You can pour spring water into one cube-holder and club soda into another.

Depending on the tastes of the drinker, you now have contained-object-groups: ice cubes with specific ingredients.  Because they are solid, you can extract them neatly from the ice tray and drop them in the drink.  But suppose your guest takes a sip and changes his mind about their choice of drink.  You look into your freezer and realize you are fresh out of ice cubes.  No problem mon!  Just pour the drink out of the glass, wash off the ice cubes and pour a different drink.  Because the ice cubes are frozen and solid, they maintain their form irrespective of the surrounding drink.  Thus they are highly reusable.

However, if you mixed your drinks with sugar, lemonade and cold water, you would not be able to extract the cold-water out of the drink to reuse in another drink.  All the contents would be so intermingled that it would be impossible to re-extract the cold water.

This brings us to another point.  It is not really the water in the ice cube that we are interested in is it?  It is really the “cold.”  The water is really a delivery mechanism for “coldness.”  So the “coldness” is bound up with the water in order to be useful, since we cannot really deliver pure cold (at least not immediately).  In the same way, in the quest for object-reuse we tend to find that the ideal of having perfectly reusable objects is not attainable.  Many times there is some level of object-intermingling within our code since the ability of individual objects to perform useful tasks by themselves is very limited.

The promise of object-oriented software was code-reuse.  In reality, because of the way in which objects are instantiated or refer to each other, code quickly becomes un-portable.  Without uprooting a lot of other surrounding classes, we cannot really achieve the code reuse we desire. This brings us to the concept of Containable-Object-Groups.  These are sets of objects which can be lifted out of our code, packaged into a library of functions and reused by several clients.  All this is in a manner similar to lifting a whole ice cube out of a drink and dropping it into another.

From studying design patterns I have come to the conclusion that most of the time code reuse will not come about by trying to extract individual objects and reusing them.  Really useful code tends to have objects that have some knowledge of other objects.  However, reuse can be attained at the COG level by packaging the interchangeable classes, the interface they conform to and the factory class which selects among them for return to the client.  The COG concept is really a repackaging of an idea that most folks already know as black-box-reuse.  You can think of COG's as the black-boxes in design patterns.  Even so, they are not black-boxes in the pure sense since their code has to be adjusted to the situation they are being adapted to.

COG's in code are similar to cog-wheels in real life.  A cog-wheel is made up of the inner-hub which allows it to rotate on a spindle (a row of teeth which will spin against another cog-wheel and the body of the cog which connects the teeth to the hub).  In the same way that we cannot reuse the cog’s teeth by themselves, we tend not to be able to reuse individual objects by themselves.  However, design patterns allow us to consciously design our objects in containable-object-groups, which allow for a high level of reuse.

In the sample code you will see the reusable COG's in namespaces and assemblies.  Usually the COG is separated from the client and the client has a reference to the COG.

 

Delivery Mechanisms

Within each containable object group, we attempt to draw an imaginary line around the classes in the group and isolate them from the outside world.  We then make the product classes friends of the classes in the group, but private to everyone else.  We also introduce a delivery mechanism into the group.  This delivery mechanism is responsible for delivering the product classes (the classes that do work) to the client code.  Deliver mechanisms are of two main forms, active and passive.

 

Passive Delivery Mechanism

A passive delivery mechanism is usually an interacting-interface with which client code will interact.  Instead of instantiation classes as themselves, clients instantiate them as the parent interface which they implement.  This frees the client code from having to know which class it will use until run time.

 

Active Delivery Mechanism

An active delivery mechanism is usually a factory class which accepts a parameter from the client and returns the appropriate class to the client.  This allows us to add new classes and modify existing classes easily, since the factory will worry about how to best translate the requirement stated by the client into an object that performs in the specified way.

Active delivery mechanisms include passive delivery mechanisms because the factory will return the class as the interface, thereby maintaining transparency.

 

Broken Ice-Tray

In the days when procedural code ruled, the antithesis to well structure code was spaghetti code which allowed the execution to jump all around in the code.  In my readings I have not seen a term in object-oriented development which mirrors the concept of spaghetti code.  So again, being the overly-brave person I am, I will attempt to coin the "Broken-Ice-Tray" concept.

An ice tray which is broken allows water to freeze in an un-partitioned manner and thereby prevents the easy separation of the ice cubes.  Object oriented code that has classes that break encapsulation by embedding a lot of knowledge about each other I refer to as a “Broken-Ice-Tray.”  You could also call it the "Pot-of-Ice."

 

Extra-Pattern-Issues

Some issues have little to do with the topic at hand (design patterns).  An example is the use of an oledbcommand object with a datareader configured to return a single row versus using an oledbcommand object with an SQL which returns a single row.

On the other hand, substituting a MustInherit (abstract) class for an Interface is generally a pattern issue.

 

Intra-Pattern Issues

Intra-Pattern Issues are issues which are internal to the pattern.  By default the issues are intra-pattern and so the term is hardly used.

 

Inter-Pattern Issues

These are issues which affect the way in which other patterns would interact with this pattern and aid in its operation.  Because the other pattern is named in the inter-pattern discussion, the term “Inter-Pattern issue” is hardly used.  It is obvious that the mention of another pattern amounts to the same thing.

 

Pattern-Safety

This speaks to the issue of the recognizability of the pattern.  Imagine you have a problem with your jet-ski and you bring it to your trusty car-mechanic who has worked on cars for 20 years.  An engine is an engine, right?  But he may or may not understand how to fix it because there is a chance he may not recognize the components and how they fit together to make the jet-ski work. This is why you have people who fix jet skis and those who fix cars.

That is the risk you run when you spice up a pattern, cut an interface or add a product-class.  Code maintainability hinges on people being able to look at your code and quickly see the pieces and how they interact.  Patterns give you that predictability and recognizability.  But if you modify the pattern because at a particular point in time one of the participants was not critical to its function, then you lose pattern safety.  Pattern safety is the guarantee that other developers who have expertise in design patterns will be able to maintain and extend the code or reuse the COG's in the pattern (see definition above).  Developers who are responsible for keeping your code running may be in for a warm and unpredictable time if you carve up the pattern arbitrarily.

Achievement of pattern safety is one of the reasons I hope that there will be pattern standardization committees who work towards solidifying how the patterns should look and feel in all the major languages, along with all the acceptable variations (with a name and code for each variation).

Conclusion

I hope you found this article beneficial in regards to the terms you should know when using patterns in VB.NET.



User Comments

Title: Vb.net   
Name: Sathiya
Date: 2010-12-29 2:45:58 AM
Comment:
I want to learn vb.net basic controls with example
Title: vb.net   
Name: d.sravan
Date: 2009-09-04 3:26:06 AM
Comment:
i want to learn vb.net basic codes and commands with examples.
Title: vb.net   
Name: M.Riaz
Date: 2009-02-06 10:34:13 AM
Comment:
My Email is gccriaz@yahoo.com.
I want to learn gridview behaviour also inform me how can I pick value from a perticular cell.
Title: vb.net   
Name: john
Date: 2007-08-31 12:49:47 AM
Comment:
i neeed to learn vb.net basic codes and commands in 10 days.

MY mail id is john.earnest24@yahoo.com
kINDLY DO THE NEEDFUL.
Title: Feedback   
Name: Matt
Date: 2007-07-17 1:24:14 PM
Comment:
What is the GoF book?
Title: Feed Back   
Name: Suresh
Date: 2007-01-11 5:23:43 AM
Comment:
The article is good.I got some idea to implement design patterns

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-19 5:44:14 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search