ISA TRANSACTIONS' ELSEVIER
ISA Transactions 33 (1994) 367-375
An object oriented approach to batch programming S a m u e l L. S h a r p l e s s
a,,, R i c h a r d
J. W i n s l o w
b, M i c h a e l W . S a k m a r
a
a Instrument Control SerL'ice, P.O. Box 7126, Pensacola, FL 32534, USA h E1 DuPont DeNernours and Co, 666 Drit.,ing Park At'e, Rochester, N Y 14613. USA
Abstract
Object oriented programming is a method of organizing a program, its data and functions into logical units that can be individually addressed. Industrial applications are well suited for this approach due to the modular nature of process design. However, batch programming languages do not currently provide the necessary structures and programming tools needed to properly implement true object oriented code. This paper discusses a method for implementing an object oriented approach to batch programming using existing batch compilers. A simple system is provided as a case study in the approach. Keywords: Batch control; Object oriented programming; Software engineering; Modular batch
1. Introduction
Object oriented programming (OOP) is a programming method that has received a lot of attention in the past several years. It has proven its effectiveness in a multitude of applications, although it has not yet made significant progress in control systems, since the methodology has not yet been embraced by batch system vendors. To make full use of OOP, the compiler itself must be O O P based in order to provide the tools necessary to truly implement OOP. However, the application to the industrial environment is strong, and the organizational aspects of O O P is useful in large systems. This p a p e r is an attempt to implement some object oriented principles using existing batch compilers. This approach has already resulted in real benefits in the ability to
* Corresponding author.
understand, maintain and share the code at several sites. This paper is a case study of a batch programming project that was begun at the end of 1991 by El DuPont's Imaging Systems Division. The project objective was to design a modular code for use at multiple facilities within a site and at multiple sites, with each implementation having relatively similar hardware design. The original architecture of the code used object oriented philosophy, although the programming itself was not in this style. When the second facility needed to begin utilizing the first facility's code, the object oriented software design was not clearly visible within the code, thus more stringent coding rules and practices were implemented to delineate objects and their differences. The total project now includes about 180 production units (vessels, headers, etc.), with each unit's batch programming in the 5,000 to 15,000 line range. This sounds like more code than it actually is, since the OOP-like structure has allowed for 60
0019-0578/94/$07.00 © 1994 Elsevier Science B.V. All rights reserved SSDI 001 9-0578(94)00042-5
368
S.L. Sharpless et aL / ISA Transactions 33 (1994) 367-375
to 80% code reuse so far (some basic functions may be in every routine unchanged, since there is no ability to link programs), and this ability to share is expected to grow as the architecture does.
[ MOTOR BOAT 11 ENGINESIZE CRUISE Fig. 2. Class-and-object.
2. Classical object oriented programming The use of objects for analysis, design and implementation is gaining popularity for many reasons. First, the twenty year evolution of object oriented programming (OOP) technology has improved object oriented analysis and design to a level where they are easy to use. Secondly, the use of object oriented technology improves the stability of a system. That is, the objects (the real world vessels, motors and transmitters) are much more stable than the methods (procedures and functions) that act upon them. Therefore, if objects are used as the building blocks of the system, it follows that the system will be more stable than if structured techniques were used. Lastly, systems are becoming more and more complex and the use of objects helps to manage this new and added complexity [1, p. 2].
2.1. Object oriented principles In order to understand more about OOP, some common principles need to be examined. Since the object is perhaps the most important idea to understand, it will be discussed first.
attribute values and their exclusive services [1, p. 26]. An attribute is a piece of information that describes some characteristic of an object. For example, hair color, eye color, height and weight are all attributes belonging to a person. A service is some behavior that an object exhibits. For example, eat, sleep, walk and talk are all services belonging to a person. C o a d / Y o u r d o n notation will be used in this paper. This notation includes a symbol that represents a class and a symbol that represents a class-and-object. A class can be defined as " A description of one or more objects with a uniform set of attributes and s e r v i c e s . . . " [1, p. 26]. A class-and-object represents a class and all the objects in the class. In layman's terms, a class can be simply a very abstract grouping (like "all reactor vessels"), while class and objects are things or groups of things that are real and concrete (like " R e a c t o r vessel #5"). The symbol for a class is shown in Fig. 1, while the symbol for a class-andobject is shown in Fig. 2. The top section of the symbol represents the name of the class. The middle section of the symbol lists the attributes of the class, while the bottom section of the symbol list the services of the class.
2.1.1. Object Coad offers the following definition of an object: An abstraction of something in the domain of a problem or its implementation, reflecting the capabilities of a system to keep information about it, interact with it, or both; an encapsulation of
CONTAINER COLOR CAPACITY DRAIN FILL Fig. 1. Class.
2.1.2. Inheritance According to Booch, "inheritance defines a relationship among classes, wherein one class shares the structure or behavior defined in one or more classes" [2, p. 54]. This means that classes inherit structure, meaning associations, as well as attributes and services from the other class or classes. The class that inherits is said to be a specialization of the class from which it inherits. The class that a specialization inherits from is called a generalization. Single inheritance occurs if a class inherits from only one other class, while multiple inheritance occurs if a class inherits from
S.L. Sharpless et al./ ISA Transactions 33 (1994) 367-375
BOAT LENGTH BEAM REGISTER CRUISE
calling B O A T _ C R U I S E . The benefits of polymorphism are so numerous and important that polymorphism is a cornerstone of OOP.
2.1.4. Encapsulation
+
II
I
SAILBOAT NUMBEROF_SAILS CRUISE-
1
369
I
II MOTORBOAT11 ENGINE_SIZE CRUISE
Fig. 3. Single inheritance.
two or more other classes. Fig. 3 is an example of single inheritance. That is, the class-and-object M O T O R B O A T and the class-and-object SAILB O A T both inherit the attribute L E N G T H , the attribute BEAM and the service R E G I S T E R from only one other class - BOAT. Single inheritance is the most common, therefore, multiple inheritance will not be referenced in this case study.
2.1.3. Polymorphism "Polymorphism is a concept in type theory in which a name ... may denote objects of many different classes that are related by some common superclass" [2, p. 102] is Booch's definition of polymorphism. Polymorphism means that a service defined in a generalization can be handled differently in each of its specializations. Fig. 3 contains an example of polymorphism. Classand-objects M O T O R B O A T and S A I L B O A T both inherit from the class B O A T and contain some of the same services. The service C R U I S E is in both of the specializations, but cruising a sailboat is much different from cruising a motorboat, therefore, the services perform different actions. If the service is called in the class BOAT, the correct service will be executed depending on which one is appropriate. This gives the system flexibility since it does not matter which kind of boat the object is, the service can be initiated by
Encapsulation is hiding the details of the implementation of an object or program, such that the user of the object or program does not need to know its inner workings. An example of encapsulation occurs when you drive your car. You do not have to know how an internal combustion engine works and you do not need to know what kind of steering system your car uses; you only need to know how to initiate the "services" (like crank, go, stop, turn) of your car. Of course, a program or system can exhibit encapsulation without being object-oriented, but if a system is object-oriented, encapsulation will occur. The use of encapsulation in s y s t e m / p r o g r a m design is essential for managing the complexity of the syst e m / program.
2.2. Control .~ystem class-and-objects One simple example of a class-and-object in a control system is a valve. A valve might have attributes like max-output, min-output and current-output. A simple valve might have services like open and close, while a more complex valve might have services like open-percent which allows the valve to be only partially open. If the valve was designed and programmed as an object, these operations would only be defined once, but could be used for practically any valve in the system.
3. Application to a batch programming environment
This paper assumes that an object-oriented compiler is not available. The authors have done their development relative to this p a p e r using Batch-90 version 3.2 on the Bailey Infi-Nct system. (Bailey, Batch-90 and Infi-Net are trademarks of Bailey Controls Company, Inc.) This is a compiler based loosely on the popular F O R -
370
S.L. Sharpless et al. /15.4 Transactions 33 (1994) 367-375
TRAN and BASIC format. References to a particular compiler will be avoided in the following discussion.
pH must be calculated from the amount of water, acid and manually added ingredients. This example ignores any other I / O for the sake of simplicity.
3.1. The process 3.2. Definition of objects Let us take a very simple system and build up an object oriented design for it. Refer to Fig. 4. There are three mix vessels where various raw ingredients are mixed. All have level transmitters, but only Mix vessels 1 and 3 have temperature regulation. There are temperature transmitters in the vessel and on the jacket recirculation outlet. All three mix vessels have flow valves from the main water supply header, although a single shared flow meter is used for dispensing of quantities to any vessel. The reactor vessels (#11 and #12) have temperature control and level transmitters just like the mix vessels. All of the reactor vessels have flow valves from main supply headers for process water and acid. Reactor 11 has pH indication from a transmitter in the kettle, while reactor 12
Once all of the control logic has been resolved, basic software design must be addressed. In most industrial applications, the logical choice for defining objects is the production unit. An example of a production unit would be a single vessel, a single header or a rail unloading station. These items are usually easily identified because the plant designer thinks about these things as units. We, as controls engineers, have to stop here for a moment and appreciate how fortunate we are. Object definition, in more abstract circles such as banking, stock tracking or air traffic control is a monumental task. These problems are laid out in dimensions somewhat less modular than our own, requiring serious investment in manpower simply to define objects. Most batch compilers, including
WAma "f--if] HEADER
ACID
II
rll-
Fig. 4. Sample system layout.
II
S.L. Sharpless et a l . / ISA Transactions 33 (1994) 367-375
Batch-90, are designed to handle each unit as a single program, thus batch programs are simply a collection of data and services for a particular production unit (an object!) in a larger system (a production train, a plant site, etc.). From now on, object names will be capitalized.
3.3. Developing the O O P model Normally, the services and attributes needed for the U N I T class would be evaluated before moving ahead to determining inheritance and polymorphism. However, let us jump ahead and diagram the inheritance structure of this sample system, considering only "seat of the pants" knowledge about how the physical objects are put together. This is not recommended for true object oriented analysis, but it may help those less familiar with O O P to know the whole picture. In Fig. 5, the U N I T class has been separated into two types, VESSELS and H E A D E R S . They are different in the field, and from the programming perspective they are different as well; vessels may have levels and temperatures, headers may have flow control and valving. We only have two specializations of the H E A D E R class, the W A T E R _ H E A D E R and the A C I D _ H E A D E R (which are class-and-objects). We have two types of VESSELS, M I X _ V E S S E L S and R E A C T O R VESSELS. There could be a very good argument in this case that we do not need to further subdivide vessels into two classes. Someone attempting to improve the programming structure might argue that the differences between the two vessels are so small that two classes are not necessary. In this case, it is important to r e m e m b e r that there is more to a U N I T or VESSEL than what is on the process drawing. These two VESSELS are likely to operate in very different ways and with different production parameters, so when changes are made in the system or the way it operates, it is likely that only one class of vessel will be modified. Tying their code together would therefore be ill-advised from the long term support standpoint. Just as with the H E A D E R S , we have identified class-and-objects at the final layer.
371
3.4. Generalization - specialization structures Now that we have a road map, let us take a closer look at attributes and services. In the example there are only four services that all of our units need to have, regardless of whether the U N I T happens to be a vessel or a header. They are: 1. Display a message to the operator; 2. Ask the operator a question and wait for a y e s / n o or number returned; 3. Send an unsolicited message to another program using proper protocol; 4. Receive a message from another program using proper protocol. We now havc four services that are part of the U N I T object. These services will be inherited as a service to every object (program) that is in our system (wc will talk about how this happens later). But before moving on, there is something important about thesc four services. Two of these services have to do with the operator interface, and two of these services have to do with communications to other programs. If these serviccs were simply a function or two that returned a value, the obvious answer would be to just leave them as services under the U N I T class. Unfortunately, neither of these tasks are straightforward. Operator interfaces, especially for operating batch programs, are relatively complex, usually requiring coordination with control logic, operator stations and graphic displays. It is not unimaginable that the final operator interface routines might inelude several hundred lines of code. The same can be said for the service of coordinating with other batch programs and handling protocol. If all of this code is in the class U N I T without organization, it will be very difficult later to make any sense of the code. Thereforc, the objects have been broken into encapsulated parts, which will be referred to as part-objects. A part-object O P E R is created to represent the operator interface, which is a part of UNIT. O P E R will have two services, O P E R _ D I S P and O P E R Q U E S T I O N , that fit the specifications for services one and two above. We will also dcfinc a part-object C O M M that has two services, C O M M S E N D and C O M M LISTEN, mceting servicc specifica-
372
S.L. Sharpless et al. / ISA Transactions 33 (1994) 367-375
tions three and four above. This has been represented in Fig. 5 by justifying the part-object names to the left and indenting the services or attributes
that belong to them. There is a "better" OOP way to represent this relationship, but the drawing soon becomes complicated beyond the scope
UNIT COMM COMM SEND COMM-LISTEN OPER OPER_DISP OFqER_QUESTION
I
HEADER
VESSEL COMM COMM_WATER_ADDR
COMM COMM_DISPENSE FLOW FLOW_SETRATE
COMM COMM_HEADER_REQ TEMP TEMP SET TEMP STATE TEMP GET LEVEL LEVEL_GET
+
+
MIX
I
I r
OPER OPER ADD
t
J
I
~ L
I TEMP TEMP PROFILE
÷
]
MIX 1
MIX 2
OPER OPER_I/O TEMP TEMP_I/O LEVEL LEVEL_I/O
OPER OPER_I/O TEMP NULL LEVEL LEVEL_IO
OPER OPER_I/O FLOW FLOW_UO
OPER OPER_I/O FLOW F LOW_l/O
FLOW FLOW_SET_PATH
FLOW FLOW_SET_PATH
m,
1
REACTOR t
MIX 3
OPER CXOER_I/O TEMP TEMP_I/O LEVEL LEVEL_[/O
HEADER_ACID
HEADERWATER
REACTOR COMM COMM_HEADER_ACID_ADDR TEMP
OPER OPER_I/O TEMP TEMP I/O LEVEL LEVEL I/O PH PH_I/O PH
PH_OET
Fig. 5. Generalization and specialization diagram.
1
REACTOR2 OPER OPER_I/O TEMP TEMP_I/O LEVEL LEVEL I/O PH • PH_GET
S.L. Sharpless et al. / ISA Transactions 33 (1994) 367-375
of this paper, and the format shown is much more useful for our purposes. You will see that the service list on the U N I T class is in two sections. The section under the C O M M indention is a list of those services associated with the C O M M part-object, and the section under the O P E R indention is a list of those services associated with the O P E R part-object. In the attributes section of the U N I T class box are two C O M M attributes. These attributes represent global data declarations, attributes of C O M M that will be inherited by all objects (all programs) in the system. Likewise, all of the services for both part-objects will also be inherited. This means that one set of code and data will be written and declared for those O P E R and C O M M elements, and it will be used by all U N I T S (programs) in the system. One of the specializations of U N I T is VESSEL. As stated, it will inherit all of the attributes and services of unit. But it also adds a new part-object, TEMP. T E M P is the kettle temperature control system, which is part of the VESSEL. T E M P has two new services for VESSELS that H E A D E R s will not have. T E M P _ S T A T E will turn the vessel temperature control and jacket p u m p on or off. T E M P _ SET will set the contents temperature target for thc vessel. There is another new part-object of the VESSEL, LEVEL, which manages the level in the vessel. It has but one service, L E V E L _ G E T , which returns thc current level of the vessel in liters. There are also new items for COMM. C O M M _ W A T E R _ A D D R E S S is the water header program address. COMM_HEADER R E Q U E S T is a service that enables a vessel to complete a request transaction for any valid header. Notice that these new C O M M services and attributcs add to those C O M M services inherited from UNIT. Review the rest of Fig. 5, paying special attention to how inheritances and specializations are used and how the part objects modify and add to the parts on down the tree. Notice an unusual situation in the R E A C T O R class. Normally, a part-object PH would be there to manage the p H reporting for the reactors, with a service P H _ G E T that would return the pH value. However, that functionality has been forced into each class-and-object in order to account for the physi-
373
cai difference in reactor I / O . A similar situation occurs with the H E A D E R class and F L O W _ P A T H _ S E T , which must handle different valve arrangements in each header. In M I X _ V E S SEL_2, there is no temperature control, so a service has been added called T E M P _ N U L L . T E M P _ N U L L is a set of blank services that overwrite and therefore eliminate the inherited services. This eliminates the need to make M I X _ VESSEL_ 2 a specialization of U N I T (that would be difficult to handle) due to this simple anomaly.
3.5. Considerations Although changes inside an object can be made without impacting other objects, if the interface to any object changes (meaning function or procedure parameters) other objects will require modification to incorporate the changes. Care must be taken in the design of an object in order to provide a stable interface to its scrvices. Many engineers may not feel that a separate servicc (function) is nccessary to do a simple job like T E M P _ S E T or L E V E L G E T . Why not just get the vessel level directly from the global I / O value? Let us say that a product change requires batch code to make a specific gravity correction, unit conversion, barometric correction, etc. That direct I / O access may be in the code 200 separate times, it could take a very long time to evaluate and make the changes, much less test the changes individually. But by using the L E V E L _ G E T function to encapsulate (hide) that data, the L E V E L _ G E T routine can be modified at the VESSEL class once and for all. Or, the location of a function like LEVEL_ G E T could be moved down the generalization-specialization ladder (in the same way P H _ G E T is split among R E A C T O R classes, to create a separate calculation for one or more objects. Even better, whatever method is used can be resolved completely inside a part object without worry about consequences of missing an explicit I / O access that could be anywhere in a program. Notice that all attributes and services have been defined with the name of the " p a r t " as the first phrase in the service name. This is done due
374
S.L. Sharpless et al. / ISA TrarL~actions 33 (1994) 367-37.5
to the universally global nature of batch compilers. There is nothing to prevent improper use of services to operate on data that is not an attribute of that "part". That is, a routine such as L E V E L _ G E T may (illegally, in our pseudo-OOP structure) access the temperature of the vessel by directly (and improperly) accessing the temperature I / O point, instead of using T E M P GET. Having the name of the " p a r t " in service and attribute names reminds the builder of any service that " p a r t " owns an attribute, hopefully preventing a coding error. It also allows violations of the " p a r t " structure to be more easily located during code reviews. Relatively simple "policing" programs can also be written to validate attribute access. An additional protocol may also be employed to emulate the "private" functions of OOP compilers, by requiring that functions end in _ GF for (public) global functions or _ LF for (private) local functions. In this context, only functions in the same " p a r t " may call an _LF.
3.6. Implementation Now that the pseudo-OOP approach has been defined, how can this be implemented in a nonOOP compiler? First, each class-and-object is given a two letter identifier. The mix vessels can be M1, M2 and M3, the reactors R1 and R2, and the Headers HW and HA. All of the other classes should be given an identifier too, hopefully something meaningful. In this example, MX will represent the class MIX VESSELS, RX will mean REACTORS, VX will mean VESSELS, and XX will be used for UNIT. Then, each part-object is given a name of up to six letters: COMM, OPER, TEMP, LEVEL, FLOW and PH. Now the attribute (or data) files are built. All of the attributes listed for each object are placed into a file named for both the object and the part. Mix vessel 1 temperature control attributes go into a file called M1TEMP.DAT. The reactor 1 pH transmitter is declared in R1PH.DAT. COMM_ ACID H E A D E R goes into RXCOMM.DAT. C O M M STATUS goes into XXCOMM.DAT. The same procedure is now repeated for the services (functions), except they arc placed into .FUN files. O P E R - A D D goes into MXOPER.
FUN. The acid version of FLOW_ P A T H SET goes into H A F L O W . F U N and the water version goes into HWFLOW.FUN. C O M M _ S E N D goes into XXCOMM.FUN. Now comes the implementation of inheritance and specialization. Starting at the class-and-object, work through the inheritance tree including files at each class. The batch program file for mix vessel 1 would look like: {Data section} INCLUDE( M1OPER.DAT) INCLUDE( MICOMM.DAT)* INCLUDE( M 1TEMP.DAT) INCLUDE( M1LEVEL.DAT) INCLUDE( VXCOMM.DAT) INCLUDE( XXCOMM.DAT) INCLUDE X X O P E R . D A T ) {Function section} INCLUDE(MXOPER.FUN) INCLUDE(VXTEMP.FUN) INCLUDE(VXTALK.FUN) INCLUDE(VXLEVEL.FUN) INCLUDE(XXCOMM.FUN) INCLUDE(XXOPER.FUN) * this file would be empty and may be omitted Compilation now produces an object file containing only those specialization routines valid for this class-and-object program and it has inherited functions from successively higher generalizations. "Null" situations, such as the lack of the T E M P part on mix kettle 2, are accommodated by not including any include files of that part.
4. Conclusion
OOP offers well organized and isolated segments of code that allows the software to evolve. Changes can be made to one object without effecting the rest of the system; this helps prevent unexpected impact to previously working components and translates into reduced production downtime and greater operations confidence in the system. The use of OOP can reduce the largest lifecycle cost of a software application - software
S.L. Sharpless et al. l I S A Transactions 33 (1994) 367-375
maintenance. Ease of maintenance is OOP's largest asset by: 1. Being able to go to one place to fix an error that occurs globally. 2. Limiting the possible consequences of a change to a particular section of code. According to Coad "Most organizations recognize that 75 to 80 percent of a system's cost occurs after it has been deployed; this also means that many of the defects are discovered after deployment, and, even more important, much of
the functionality of the system is added after initial deployment. Thus, a method that emphasizes maintenance improves productivity by enabling maintenance programmers to make modifications more quickly [1, p. 14]". Even a well designed manufacturing facility evolves to improve quality, accommodate new products and improve efficiency and cycle time, which requires evolution of the software. Traditionally, each facility is a single project. But as companies consolidate products and manpower, there is a stronger desire to have several plants use common software structures and code in order to save software development dollars, non-revenue generating start up time and software maintenance costs. OOP is a realistic way to meet these goals. It allows companies to build
375
object libraries that are pre-built, debugged process control elements that can be used to build up a project. With each process segment defined as a separate object, the process elements can be mixed and matched just as the hardware elements are. As with any software design, when multiple developers are working at multiple sites on the same code, code management procedures and principles must be given a high priority. Many softwarc packages are commercially available to meet this need. Among the several software engineering methodologies, OOP is the best suited for industrial applications. Although OOP compilers are not yet available for control applications, there are relatively simple programming rules and practices that can help implement this methodology. It is expected that vendors will soon provide products that will enable the controls community to fully cmbrace OOP.
References [1] P. Coad and E. Yourdon, Object Oriented Design (Prentice llall, Englewood Cliffs NJ, 1991) [2] G. Booch, Object Oriented Design with Applications (Benjamin/Cummings, Redwood City CA, 1991).