(c) Peter E. C. Dashwood - 2017
What COBOL people NEED to know about Classes and Objects
We have seen that for COBOL to run well on the Network it has to change the paradigm it was originally designed for:
(Procedural processing on a centralized processor.) We have also seen that the new paradigm is best served by small blocks of code, and these are best implemented using the Object Oriented Programming model.
Most COBOL programmers have steered clear of learning about Object Oriented Programming (OOP) because they never saw the need for it. (Hopefully, as you are reading these pages, you may be changing your mind about that.) It IS a large topic and is dealt with more properly elsewhere on this web site, but, for now, there are some things you NEED to know about OOP so we can progress:
1. OOP deals with CLASSES of things. For now, you can think of a Class as being a "collection of things". When you need a copy of the things in the collection, the Class can make a copy of itself. This is called an "instance". Each instance can behave independently of the Class it represents and each instance gives you a reference to itself. You can use this reference to access the "things" in your instance of the Class. (These "things" are generally behaviours, in the form of "methods", and data in the form of "properties" or "attributes"; your instance contains code and data...).
2. An OBJECT is an instance of a Class. The tangible evidence for the existence of your object, is the reference to it that you received when you asked the Class to make an instance of itself. This OBJECT REFERENCE gives you access to everything the Class contains, implemented by your specific copy of it. (Your instance.)
IMPORTANT THINGS TO NOTE in the diagram:
1. An OBJECT represents a Class, and it provides access to the items in the Class. For normal programming, as we only see the Object, we tend to talk about Objects rather than Classes.
2. When an Object is created, the creation process passes back an OBJECT REFERENCE to the requesting process. (Your application program will normally be the requesting process.)
3. ALL access to the properties and methods of the object is through the OBJECT REFERENCE. The Object Reference is aware of the technical INTERFACE required for every item contained in the Object, and you can only get access to the things in the Object through their individual interfaces, as presented by the Object Reference for the Object. Notice that different methods and properties in the object will each have their own interface. (This is called a "signature".) You access an item by invoking its signature on the Object Reference.
4. The Object interfaces provide SEPARATION between the things inside the object and the applications that want to use them. This has important implications when it comes to making changes to code. Because of this SEPARATION, Objects are said to be ENCAPSULATED. NOTHING OUTSIDE the Object can affect what is inside it. (Obviously, values of things inside can be changed through the interface, but the processes themselves cannot be affected by changes to code outside the Object. Generally, If you change the code inside a Class it CANNOT affect code in ANY OTHER Class. The older Procedural paradigm was famous for the "knock-on" errors that could occur; these are effectively reduced or eliminated by Object Oriented Programming.
5. There is a special type of "standardized" Object interface which provides a simple, consistent way to communicate with Objects. It is described under the "Component Object Model (COM)" documentation from Microsoft. COM objects (COMPONENTS) can be written in, and invoked from, ANY language that implements the COM interface. (Including OO COBOL...) You can embed these components into web pages or use them on the desktop. You can build entire systems by assembling Components like Lego blocks. (Over 90% of all Classes written by PRIMA today (in C# OR OO COBOL) are COM compliant and can be used almost anywhere.)
So, how does OOP help us with our event-driven paradigm?
Application programs in general can be divided into a series of interacting functions, which represent "areas" of
program code. A simple example would be to say: "My application has to address 3 areas:
1. Interaction with the user (if it does...)
2. Managing data
3. Applying Business rules to the data it is managing." (There can be other areas like "Printing Reports", "System function Requirements (Housekeeping)" and whatever you decide is a collection of similar or related functions; it is just an example...)
Within these "areas" there will be functions that get used all the time, functions that are used moderately, and some that are seldom used. Applications get built by using functions from across all of these areas.
For PROCEDURAL Programming, we are not required to make code small so we just grab or write code inline and probably never even think about the "areas" view of the application. Write the code as an integrated monolithic program, test it, fix it, done! The result is duplicated (or very similar) code (sometimes the same function written by more than one programmer) across different applications. Early COBOL programs were written on this model; as time went by attempts were made to cut down on the duplication (COPY, INCLUDE, Modular Programming...) and RE-USE existing code.
Because there is no ENCAPSULATION, maintenance becomes labour intensive (costly), time-consuming, and difficult. A function might be fixed in one application but not in another that uses the SAME function (but implements it with different code). Regression testing of the entire system is needed to make sure that ALL required changes have been applied and are working.
For EVENT DRIVEN Programming, the immediate priority is to service the current event. Most events are raised by one "area" of the application: The interaction with the User. (Graphic User Interface - GUI). We want code for the GUI layer to be small, so it can load and execute quickly, so we really don't want this code "cluttered" with code from other layers. Therefore, it makes sense to adopt a layered approach to system design. If layers are recognized, then the functions within a layer can be recognized. Classes can be written for each layer. Layers can communicate through the Object interfaces of their Classes.
A quick example:
If an Object in the GUI Layer is given a Customer ID, and it needs to update a Form on the screen with the Customer address details and Account balance, we really don't want it including all the code to do that, within itself. Instead, it gets an Object Reference to a service method in the Data Access Layer (DAL object) and puts the Customer ID in the interface to that DAL object. It invokes a method of the DAL object and receives back in the interface the data for the customer. It gets an Object Reference to the Form and uses it to reference the control which displays the customer data, passing the customer data to the interface for that control on the Form. So, in terms of space, the "extra" overhead was 2 object references. (The interfaces are already part of the WS and passed as LINKAGE).
You can write ALL of the above in OO COBOL!!
Sadly, when OOP was added to COBOL back in the 2002 standard, most people
in the COBOL community rejected it. Even in the late 1990s some vendors were already adding OO facilities to their
COBOL and the very few "early adopters" (I was one...) were met with scorn and derision when they expressed that
there could be some value in this approach. The World voted with its feet and moved to the Network. Objected Oriented
Languages (for all the reasons we have been looking at) swept the board, and by the time the COBOL people realized it
might be good to learn about Object Orientation, the ship carrying it was a distant smudge on the horizon.
So now, when it becomes necessary to migrate the Procedural legacy to the Network, the fact that this involves a paradigm shift is generally not recognized. Just compile the existing code for the new platform or get it generated into Java and we can carry on as usual...(This can result in needing to extensively upscale the Network, which kind of negates the cost savings you were looking for when migrating in the first place.)
If you are reading this because you are considering migrating your legacy COBOL to .Net, please think carefully about the points being made here; they are based on experience and will save you money if you do.
1. Event driven environments lead us to the recognition of LAYERS in the software
2. Designing Classes for layers leads us to the recognition of COMPONENTS.
3. Components, Classes, and Objects are ENCAPSULATED. This has major benefits when maintaining them.
4. ANY change to a Class in ANY Layer CANNOT affect other Classes in the same or any other layer. (Classes which inherit from another Class are exceptions to this, but generally it is true...)
5. Layers remove duplication of code from a system.
(This completes the arguments for Objects & Layers when using the Network. Existing code CAN be re-factored to comply with this model and it really SHOULD be, if you are migrating it to .Net. There are tools available, or some simple guidelines can help you do it manually. Contact PRIMA for details...)