Are You OOPing in .NET Yet?

By Peter A. Bromberg, Ph.D.
Printer - Friendly Version

Peter Bromberg

Some programmers are lucky - they studied Object Oriented Programming (OOP) in college, or were personally tutored by a master programmer, or were just plain so smart that somehow they started out OOPing and never had to change their perfect ways. Folks like me, who wrote their first programs in Applesoft BASIC on PC's with 64K of RAM, aren't that lucky. We had to learn it mostly via the brute force approach which usually mostly involves "unlearning" all the bad programming habits we used to think were so great.



Now that .NET is making its mark on the hearts and minds of programmers and their clients worldwide, it might be prudent for all of us whether we are VB.NET, C#, Eiffel or Perl programmers, to revisit OOP and try to spend more time understanding how it can help us solve the problems of the world.

So let's first recap the three "Pillars of OOP", presented as my personal "take" on it:

1) OOP is Encapsulation:
Hiding Data, but defining properties and methods to let the caller have access to it. OOP succeeds only when you manipulate data inside objects, only sending requests to the object. This "Data Hiding" is critical to both successful reuse and long-term reliability of components.

2) OOP is Inheritance:
The concept of deriving classes from a base class where the derived class "is a" one of the base class (e.g. a Manager "is a" Employee). Inherited classes are always more specialized than their base (parent) classes, have at least as many members (although the behavior of individual members may be different) and often have new methods
that have no counterpart in the base class. There are various types of inheritance. Interface inheritance inherits only the interface signature, while implementation inheritance inherits the actual code implemented in its parent. Another subset of Inheritance, and often referred to as the fourth "Pillar of OOP" is Aggregation, where the method of an inner component is to be directly exposed to the outside world. An object takes the inner object’s interface, and presents it as it's own. In my short article here entitled "Got Interface?" I describe some of the features of this technique.

3) OOP is Polymorphism:
This is the concept where inherited objects "know" what methods they should use, depending on their position in the inheritance chain. An "Account" object will know that if it is a PremiumAccount object, it must call the GetCashAdvance method in the PremiumAccount class rather than the one in the Account class. You do not need to know what class an object actually belongs to in the inheritance chain when you send it a request; you can just send all Account objects the same GetCashAdvance message and each Account object will automatically choose the correct polymorphic method in each object.

Object Oriented Programming is really a lot more than a “programming concept". It’s a way of learning to think in a completely new way about the process of how to design and create robust, scalable applications. With OOP, we learn to think of applications not as "sets of procedures and properties", but as objects and “beings” that are logically grouped by the way they appear, behave and function. Financial Accounts, for example, may differ in type, features, privileges and requirements, yet they’re all similar in form and function - they could all derive from the same base Account class. Coding in an object-oriented manner follows this model and, above all, it takes advantage of the ability to build on it.

The fact that code we write may contain properties and methods doesn't make it "object oriented". That COM component we wrote in VB 6.0 may contain functions that perform calculations and retain values. This component may be referred to as an "object" in the strict sense because it is an instance of a class, but it may very well not be object-oriented at all if it does not follow the principles of OOP. It's up to us to revisit that component as we get ready to migrate it to the .NET platform, and refactor the code to conform to and take advantage of OOP principles.

The key thing to keep in mind when unlearning all the procedural programming thinking we've developed is that in OOP "everything is an object". In an object-oriented approach to Bank Accounts we'll have an Account object, and we'll send a message to that object to ask it for it's current total balance or to make a deposit. We don't need to think about how the information is stored internally in the object, as we had to do with our non-object-oriented data structures. We just make requests to it by sending messages. The Account object probably iterates through a collection of detail objects, sending a message to each one requesting its current balance and probably making some specialized computations dependent on the particular Account features. However, if what we're looking for is the total, we don't care how it's done, because one of the primary tenets of object-oriented programming is encapsulation—the ability of an object to hide its internal data and methods and to present an interface that makes the important parts of the object programmatically accessible. We accomplish this by only allowing an object's methods to modify it's variables.

The key way our encapsulation is preserved is through the object's interface ( the methods and properties the users of our class can see). If you can develop a stable, static interface that persists across implementation changes, less of your application will need modification over time. This means, very simply, that If you really understand the problem domain of an application, you can determine to a fairly high degree the methods that the users of this class are going to need. You need to be able to combine expert knowledge of the problem domain with forethought and planning in the design of your class. If we can acommplish this, then we can be reasonably sure that the majority of our interface for this class will remain unchanged despite any future changes in the actual implementation of the class.

The next question that should enter our minds is "How do I go about OOPifying my program?" Here's a concise outline of the steps, in greatly simplified form:

1) In OOP, you first isolate the potential classes (which are usually the "nouns" in your programming problem). Only then do you look for the methods and properties of the class. The methods normally correspond to the "verbs" in your programming problem, and the properties are usually the "adjectives".

2) You then associate each method or property with the class that is responsible for carrying out the operation (or create a new class to do so if one has not already been created).

3) You need to identify the state, identity, and behavior of each individual object (instance of one of the classes in your project). These properties can all change over time even though the instances may seem to be "Identical".

In Visual Basic (where most of us are coming from) , we use classes to define components. Once a class is created and populated it becomes an object with properties and methods. However at this point all we've accomplished is to prove that Visual Basic can do classes with properties and methods. OOP presents a major paradigm shift especially for VB programmers who've been so blissfully insulated even from the inner workings of the COM infrastructure over the last 5 years, much less having been exposed to OOP techniques, which on the whole, classic VB simply does not support. Sure, you can get ahold of Visual Studio.NET and start writing code that will compile - code that is similar in it's old-style procedural programming techniques to the Visual Basic or other code you have become familiar with. But, you'd be missing the "OOP boat", so to speak. It's like driving an Aston Martin and never learning to get it out of second gear...

OOP is a whole way of looking at the technique of solving business problems in a reusable, extendable and performance-oriented way. It's something that doesn't come easily. It takes lateral thinking, something which Americans in particular aren't familiar with. Fortunately, there are lots of resources available in books and on the NET to help programmers move quickly into this modality and begin to reap its benefits in the form of better and more productive code, promotion of code reuse throughout the development organization, and faster time to market in solving complex business problems.

 

Peter Bromberg is an independent consultant specializing in distributed .NET solutions in Orlando and a co-developer of the NullSkull.com developer website. He can be reached at info@eggheadcafe.com