Reading Sample SAPPRESS 993 Object Oriented Programming With ABAP Objects PDF
Reading Sample SAPPRESS 993 Object Oriented Programming With ABAP Objects PDF
Reading Sample
This sample chapter explores encapsulation and implementation hiding
techniques, which are used to simplify the way that developers interface
with classes, making object-oriented program designs easier to understand,
maintain, and enhance.
Contents
Index
The Authors
www.sap-press.com/3597
© 2016 by Rheinwerk Publishing, Inc. This reading sample may be distributed free of charge. In no way must the file be altered, or
individual pages be removed. The use for any commercial purpose other than promoting the book is strictly prohibited.
Classes are abstractions that are used to extend the functionality of a pro-
Chapter 3
One of the most obvious ways to speed up the software development process is to
leverage pre-existing code. However, while most projects strive to create reusable
source code artifacts, few actually succeed in delivering modules that can be clas-
sified as reusable. In most cases, this lack of (re)usability can be traced back to the
fact that the module(s) become too tightly coupled with their surrounding envi-
ronment. With so many “wires” getting in the way, it’s hard to pick up a module
and drop it in somewhere else. Therefore, in order to improve reusability, we
need to cut the cords and figure out ways of building autonomous components
that can think and act on their own.
In this chapter, we’ll learn how to breathe life into objects by exploring the ben-
efits of combining data and behavior together under one roof. Along the way,
we’ll explore the use of access control mechanisms and see how they can be used
to shape the interfaces of the defining classes to make them easier to modify and
reuse in other contexts.
121
3 Encapsulation and Implementation Hiding Lessons Learned from Procedural Programming 3.1
achieving it in vastly different ways. In this section, we’ll take a closer look at the 왘 Parameters that are passed into the subroutine from the calling program
procedural approach and consider some of the limitations which ultimately 왘 Global variables which are visible from within the subroutine
caused many language designers to move in the direction of an object-oriented
approach. Regardless of the approach we use to supply subroutines with data, the reality is
that there’s no clean way of doing this without introducing some undesirable
dependencies. For example, if we make liberal use of global variables, we open
3.1.1 Decomposing the Functional Decomposition Process ourselves up to the possibility of data corruption errors. Here, imagine the
Typically, procedural developers formulate their program designs using a process impacts of switching out the call sequence of a pair of subroutines which make
called functional decomposition. The term “functional decomposition” is taken changes to the same global variable(s). If subroutine b depends on subroutine a to
from the world of mathematics, where mathematical functions are broken down initialize the data and the call sequence gets flipped based on a requirements
into a series of smaller discrete functions that are easier to understand on their change, it’s very likely that we’ll start seeing strange data-related errors in the
own. From a development perspective, functional decomposition refers to the processing (see Figure 3.1).
process of decomposing a complex program into a series of smaller modules (e.g.
procedures or subroutines).
One common approach for discovering these procedures is to scan through the ORDER_NO 123
functional requirements and highlight all the verbs used to describe the actions a
program must take to meet its objectives. After all of the steps have been identi- CUSTOMER 234
fied, they are then composed into a main program that’s responsible for making
sure that the procedures are executed in the right sequence. This process of orga- CREATION_DATE 6/3/15
nizing and refining the main program is sometimes called step-wise refinement. NEW A
For small to medium-sized programs, this strategy works pretty well. However, as STATUS INIT
programs start to branch out and grow in complexity, the design tends to become
unwieldy as the main program becomes saddled with too many responsibilities. ... B
CLOSED
Here, besides keeping track of all of the different procedures and making sure
that they’re processed in the right order, the main program is also normally
responsible for managing all of the data used by the various procedures. For this
Figure 3.1 Data Collision Errors between Subroutines and Global Variables
reason, such programs are often referred to as “God programs”.
Conversely, replacing global variables by passing around lots of parameters places
Note
additional burden on the main program to keep track of the parameters. Plus, we
In his book, Design Patterns Explained: A New Perspective on Object-Oriented Design, end up cluttering up the subroutine’s parameter interface, which in turn leads to
2nd Edition, Alan Shalloway suggests that the term “God program” stems from the fact
the tight coupling problem we described earlier.
that only God can understand these programs.
Ideally we’d like for our modules to assume more responsibilities internally so
With functional decomposition, the level of abstraction is the subroutine. Within that they are less reliant on controlling programs/modules when carrying out
a given subroutine definition, we can implement logic to perform a particular their tasks. Think of it this way, if we were to compare the organization of a soft-
task using data that’s provided from one of two places: ware program with organizational (org) structures in an enterprise, which of the
122 123
3 Encapsulation and Implementation Hiding Lessons Learned from Procedural Programming 3.1
two org structures depicted in Figure 3.2 and Figure 3.3 would we want our pro- 3.1.2 Case Study: A Procedural Code Library in ABAP
grams to look like? In the case of the flat org structure depicted in Figure 3.2, we To better illustrate some of the procedural programming challenges noted in Sec-
have one centralized module that’s responsible for (micro)managing lots of sub- tion 3.1.1, let’s consider an example. In this section, we’ll sketch out the develop-
modules. On the other hand, the tall org structure shown in Figure 3.3 is much ment of a date utility library using ABAP function modules.
more balanced with higher level modules delegating responsibilities down to spe-
cialized submodules. If you’ve worked with function modules before, then you know that they’re
defined within the context of a function group. In some respects, function groups
bear some similarities to classes in that you can use them to define data and behav-
iors together within a self-contained unit (called a function pool). However, this
analogy breaks down when you consider the fact that you cannot load multiple
instances of a function group inside your program. This limitation makes it difficult
for developers to work with the (global) data inside of a function group since addi-
tional logic is required to partition the data into separate work areas (or instances).
Figure 3.2 Example of a Flat Organizational Structure
Because of this shortcoming, most function module developers tend to design their
functions as stateless modules which operate on data that’s maintained elsewhere.
In this context, the term “stateless” implies that the function modules have no rec-
ollection of prior invocations and don’t maintain any sort of internal state. As a
result, function module developers need only worry about implementing the pro-
cedural logic—keeping track of the data/sessions is someone else’s problem.
Note
Whenever you call a function module from a particular function group inside your pro-
gram, the global data from the function group is loaded into the memory of the inter-
nal session of your program. Any subsequent calls to function modules within that
function group will share the same global data allocated whenever the first function
module was called.
124 125
3 Encapsulation and Implementation Hiding Lessons Learned from Procedural Programming 3.1
could have just as easily used the internal ABAP date (D) type, we elected to use a
structure type so that we could clearly address the individual components of a
date (e.g. month, day, or year) without using offset semantics.
Figure 3.5 Modeling the Data Used for the Date Library
The code excerpt contained in Listing 3.1 sketches out the date API in a function
group called ZDATE_API. Here, we’ve defined a handful of utility methods that can
be used to perform date calculations, format dates according to different locales,
and so forth.
FUNCTION-pool zdate_api.
FUNCTION z_add_to_date.
* Local Interface IMPORTING VALUE (iv_days) TYPE i
* CHANGING (cs_date) TYPE scals_date
...
ENDFUNCTION.
FUNCTION z_subtract_from_date.
* Local Interface IMPORTING VALUE (iv_days) TYPE i
* CHANGING (cs_date) TYPE scals_date
...
ENDFUNCTION.
FUNCTION z_get_day_name.
* Local Interface IMPORTING VALUE (is_date) TYPE scals_date
* EXPORTING ev_day TYPE string
...
Figure 3.4 An Example of a Stateless BAPI Function ENDFUNCTION.
FUNCTION z_get_week_of_year.
* Local Interface IMPORTING VALUE (is_date) TYPE scals_date
For the purposes of our date library example, we’ll build our utility functions as * EXPORTING ev_week TYPE i
stateless function modules. Within these functions, we’ll operate on a date value ...
ENDFUNCTION.
represented by the SCALS_DATE structure shown in Figure 3.5. Here, though we
126 127
3 Encapsulation and Implementation Hiding Lessons Learned from Procedural Programming 3.1
FORM get_data.
DATA ls_date TYPE scals_date.
DATA lt_itab TYPE STANDARD TABLE OF ...
FIELD-SYMBOLS <ls_wa> LIKE LINE OF lt_itab.
SELECT *
INTO TABLE lt_itab ...
128 129
3 Encapsulation and Implementation Hiding Data Abstraction with Classes 3.2
amount of rework within the functions themselves, this also requires that we vide an abstraction around some entity or concept (e.g. a date). Included in this
make wholesale changes to the programs that call them. abstraction is the data itself as well as a set of operations that can be performed on
that data.
Though you might be saying to yourself that the choice of the SCALS_DATE struc-
ture for the date API’s data model was a poor one (and you’re right to say so), In order for ADTs to be effective, we must keep the data and operations as close
that’s really not the issue here. The point of this demonstration is to illustrate the to one another as possible. As we observed in Section 3.1.2, such cohabitation is
fact that our date API exposes way too much information about its internal repre- virtually impossible to achieve with procedural programming techniques.
sentation. Consumers of our date API shouldn’t know (or care) whether we use Because of this divide, our date API (though admittedly contrived) was awkward
the native ABAP date type (D), a structure, or something else entirely. to use and quite error prone. These problems become even more pronounced as
By exposing this kind of information in the function signatures, we’ve effectively the size and complexity of such code libraries expand.
coded ourselves into a corner. For better or worse, we have to stick with the In many ways, all of the problems we’ve considered in this section can be traced
design choices we’ve made and try our best to enhance around them. With state- back to one central theme: poor support for data. While it would seem obvious
less modules, this is about the best we can hope for. that data is the foundation upon which any successful computer program runs,
the stark reality is that data takes a back seat to actions in the procedural program-
Dealing with External Data Corruption ming paradigm. As a result, procedural programs tend to decay at a much faster
pace than programs built using programming models which place a greater
For the next scenario, imagine that you receive a defect report which indicates
emphasis on the data.
that the Z_FORMAT_DATE function is producing invalid output. After much investi-
gation, you determine that the invalid output isn’t a function of the logic in Z_
FORMAT_DATE, but rather due to fact that an invalid day value has been specified in
the SCALS_DATE structure’s DAY field. Here, you discover that the invalid value is 3.2 Data Abstraction with Classes
set within the calling report program which is accessing the SCALS_DATE structure
Recognizing many of the limitations outlined in Section 3.1, software researchers
outside of the ZDATE_API function group.
developed the OOP paradigm from the ground up with a strong emphasis on data
Though such errors might be easy to fix once you find them, they can be difficult and behavior. As you’ve already learned, classes are the vehicle that drives this
to find. Since the ZDATE_API function group doesn’t technically own the data, equilibrium, encapsulating data (attributes) and behavior (methods) together
there’s nothing stopping other modules from overwriting and/or corrupting the inside a self-contained unit.
API’s data model. In a perfect world, we’d like all accesses to the date API’s data
Encapsulation improves the organization of the code, making object-oriented
model to go through functions in the ZDATE_API function group so that we can
class libraries much easier to understand and use than their procedural counter-
isolate them and enforce the necessary validation rules (e.g. you can’t have a date
parts. To put this into perspective, consider the clumsiness of the function mod-
value of 20160231). However, this is something the procedural model simply can’t
ule-based date library we created in Section 3.1.2. Each time we accessed one of
guarantee. To really enforce these rules, we need some support from the under-
the API functions, we had to pass in an externally-managed structure which con-
lying language implementation to control access.
tained all of the date information needed to handle the request. Plus, if we
wanted to work with multiple dates, then we had to define multiple variables
3.1.3 Moving Toward Objects and track those variables manually outside of the function group.
The ZDATE_API function group introduced in Section 3.1.2 is an example of an
Let’s compare that experience with a reimagined date API built using an ABAP
abstract data type (ADT). As the name suggests, ADTs are data types which pro-
Objects class. In Listing 3.3, we’ve created a class called LCL_DATE which provides
130 131
3 Encapsulation and Implementation Hiding Defining Component Visibilities 3.3
the same functionality of the ZDATE_API function group. As you look over the Ultimately, objects created in reference to encapsulated classes take on their
class definition, notice the simplification in the signature of the API methods. own identity, allowing developers to start thinking about their designs in more
Instead of passing around an SCALS_DATE structure, the date information is being conceptual terms (e.g. a date). Consumers of these classes don’t have to worry
stored internally in an instance attribute called MS_DATE_INFO. Besides simplifying about low-level implementation details; to the end user the LCL_DATE class is like
the interface, this design change also allows us to get out of the business of track- a black box which performs various date manipulations. We don’t have to sup-
ing date information externally. Now, our date API is truly an ADT which pro- ply the LCL_DATE class with lots of data/context/instructions; it intrinsically
vides a complete abstraction around a date value as opposed to a loosely associated knows how to do its job.
set of stateless function modules. In the next section, we’ll learn how to round out ADTs like the LCL_DATE class by
CLASS lcl_date DEFINITION. closing off access to internal components such as the MS_DATE_INFO attribute.
PUBLIC SECTION. This safeguard ensures that all operations on date values are mediated through
DATA ms_date_info TYPE scals_date.
API methods which rigorously validate incoming requests to ensure that the
METHODS:
add IMPORTING iv_days TYPE i integrity of date values is maintained. As we’ll see, this approach offers several
RETURNING VALUE(ro_date) TYPE REF TO lcl_date, important benefits.
subtract IMPORTING iv_days TYPE i
RETURNING VALUE(ro_date) TYPE REF TO lcl_date,
get_day_name RETURNING VALUE(rv_day) TYPE string,
get_week_of_year RETURNING VALUE(rv_week) TYPE i, 3.3 Defining Component Visibilities
format IMPORTING iv_pattern TYPE csequence
RETURNING VALUE(rv_date) TYPE string.
The term “encapsulation” refers to the idea of enclosing something inside of a
...
ENDCLASS. capsule. The verbal imagery associated with words like “capsule” implies that
Listing 3.3 Reimagining the Date Utilities API as an ABAP Objects Class we’re setting some kind of boundary between the internal components of a class
and the outside world. The purpose of this boundary is to protect (or hide) the
The code excerpt contained in Listing 3.4 demonstrates how we can work with inner mechanisms of the object that are sensitive to change. Most of the time, the
our refactored date library. Once an LCL_DATE instance is created, we no longer most vulnerable parts of an object are its attributes since these define the object’s
have to worry about handling the date value. Instead, we can use methods like state. However, in this book, we’ll look at ways to hide any design decisions that
add() and subtract() to apply the changes in-place. From a code readability are subject to change.
standpoint, this is much easier to follow because the context of an operation like
In this section, we’ll describe the ABAP Objects language constructs that you can
add() is clearly the object referenced by lo_date.
use to establish boundaries within your classes. Then, in the section that follows,
DATA lo_date TYPE REF TO lcl_date. we’ll consider how to use these boundaries to build robust classes that can easily
DATA lv_message TYPE string. be adapted to ever-changing functional requirements.
CREATE OBJECT lo_date
EXPORTING
iv_date = '20150913'
3.3.1 Working with Visibility Sections
lo_date->add( 30 ). ABAP Objects provides three visibility sections for controlling access to the com-
lv_message = |{ lo_date->subtract( 15 )->format( 'YYYYMMDD' ) }|.
ponents defined within a class: the PUBLIC SECTION, the PROTECTED SECTION, and
Listing 3.4 Working with an OO-Based API
the PRIVATE SECTION. Within a CLASS DEFINITION statement, all component dec-
larations must be defined within one of these three visibility sections. The code
132 133
3 Encapsulation and Implementation Hiding Defining Component Visibilities 3.3
excerpt contained in Listing 3.5 demonstrates the syntax used to define compo-
nents within these sections.
As you might expect, components defined within the PUBLIC SECTION of a class
are accessible from any context in which the class itself is visible (i.e., anywhere
you can use the class type to declare an object reference variable). These compo- Figure 3.7 Setting the Visibility of Components Using the Form-Based View of the
nents make up the public interface of the class. Class Builder Tool
Components defined within the PRIVATE SECTION of a class are only accessible
from within the class itself. Note that this is more than just a mere suggestion; this Designing Across Multiple Dimensions
is something that’s strictly enforced by the ABAP compiler/runtime environment. Choosing the right visibility section for a given component can be tricky, and it
For example, the code excerpt contained in Listing 3.6 would produce a compila- requires a fair amount of thought. Here, rather than thinking about the individual
tion error because the z attribute of the LCL_VISIBILITY class is defined as a pri- components, we need to think in terms of the class’s overall interface. If we want
vate attribute. The only way to get our hands on z is through a method defined in to make our class simple and easy to use, then we’ll need to strip down the public
the LCL_VISIBILITY class. interface to just the essentials. This makes the interface less busy and therefore
easier to consume.
DATA lo_visible TYPE REF TO lcl_visibility.
CREATE OBJECT lo_visible.
In general, clients of a class should be on a “need-to-know” basis. In other words,
IF lo_visible->z GT 0.
... if a client doesn’t require direct access to a component, then there’s no need for
ENDIF. them to even be aware of its existence. Declaring such components within the
Listing 3.6 Attempting Access to Private Components of a Class PRIVATE SECTION of a class makes life easier for everyone: clients get to work with
a simplified interface and the owners of the class have the freedom to change/
For now, we’ll defer a discussion on the PROTECTED SECTION until we have a improve the internal implementation of a class without fear of breaking existing
chance to cover inheritance in Chapter 5. For now, simply note that components client code.
defined in the PROTECTED SECTION are only accessible within a class and its sub-
classes. With this concept in mind, we’d suggest that most attributes should be defined
within the PRIVATE SECTION of a class. The primary reason for hiding attributes is
When working in the form-based view of the Class Builder tool, you can assign to ensure that the state of the object cannot be tampered with haphazardly. If a
components of global classes to visibility sections using the Visibility column client needs to update the state of an object, then they can do so through a
highlighted in Figure 3.7. method defined in the PUBLIC SECTION. The advantage of this kind of indirection
134 135
3 Encapsulation and Implementation Hiding Defining Component Visibilities 3.3
is that we can control the assignment of the attribute using business rules that are ENDMETHOD.
...
defined inside the method. This eliminates a lot of the guesswork in troubleshoot-
ENDCLASS.
ing data-related errors since we know that any and all changes to an attribute are
Listing 3.7 Working with Getter and Setter Methods
brokered through a single method. Methods that update the value of private attri-
butes are sometimes called setter (or mutator) methods. To access these values (or
As an alternative to the getter method approach, ABAP also allows us to define
formatted versions of these values), clients can invoke getter (or accessor) methods
read-only attributes within a class definition. This is achieved using the READ-ONLY
which broker access in the other direction. addition to the DATA keyword. The code excerpt below demonstrates how we
This getter/setter method approach to indirect data access is demonstrated in the might refactor the LCL_TIME class from Listing 3.7 to use this feature.
LCL_TIME class contained in Listing 3.7. Here, the state of the time object is being CLASS lcl_time DEFINITION.
represented by three private attributes called mv_hour, mv_minute, and mv_second. PUBLIC SECTION.
Any updates to these attributes are controlled through setter methods such as DATA: mv_hour TYPE i READ-ONLY,
mv_minute TYPE i READ-ONLY,
set_hour() or set_minute(). Within these methods, we’ve included logic to mv_second TYPE i READ-ONLY.
ensure that the attributes remain consistent (e.g. we don’t have an hour value of ...
113). Clients can obtain copies of these values by calling the corresponding getter ENDCLASS.
CLASS lcl_time DEFINITION. While this feature can come in handy for simple classes which are primarily used
PUBLIC SECTION.
METHODS: for transferring data, we’d encourage you to use this option sparingly since it
set_hour IMPORTING iv_hour TYPE i, exposes the internal implementation details of your class.
get_hour RETURNING VALUE(rv_hour) TYPE i,
set_minute IMPORTING iv_minute TYPE i,
get_minute RETURNING VALUE(rv_minute) TYPE i, 3.3.2 Understanding the Friend Concept
set_second IMPORTING iv_second TYPE i,
get_second RETURNING VALUE(rv_second) TYPE i. In the previous section, we learned that components defined within the private
and protected sections of a class are not visible outside of that class (or subclasses
PRIVATE SECTION.
DATA: mv_hour TYPE i,
in the case of protected components). However, in some cases, it might be advan-
mv_minute TYPE i, tageous to be able to grant special access to certain classes of our choosing. Such
mv_second TYPE i. classes are called friends of the class that grants them access.
ENDCLASS.
Listing 3.9 illustrates the syntax used to create friend relationships between a
CLASS lcl_time IMPLEMENTATION.
defining class CL_SOME_CLASS and its friends: C1, C2, and so on. Here, the FRIENDS
METHOD set_hour.
IF iv_hour BETWEEN 0 AND 23. addition is added to a CLASS DEFINITION statement to declare this relationship up
me->mv_hour = iv_hour. front to the ABAP compiler. As you can see, we can specify multiple friend classes
ELSE. after the FRIENDS addition (not to mention interfaces, which are covered in Chap-
"TODO: Error handling...
ENDIF. ter 6).
ENDMETHOD.
CLASS cl_some_class DEFINITION FRIENDS c1 c2 i3 i4.
...
METHOD get_hour.
ENDCLASS.
rv_hour = me->mv_hour.
Listing 3.9 Defining Friendship Relationships in Classes
136 137
3 Encapsulation and Implementation Hiding Designing by Contract 3.4
To demonstrate how friendship relationships work between classes, consider the As you begin working with friendship relationships, there are a couple of import-
example code contained in Listing 3.10. Here, we have a pair of classes called ant things to consider. First of all, it’s important to note the direction and nature
LCL_PARENT and LCL_CHILD which have entered into a friendship relationship. The of the friendship relationship. In Listing 3.10, class LCL_PARENT explicitly granted
LCL_CHILD class is taking advantage of this relationship by accessing the LCL_PAR- friendship access to class LCL_CHILD. This relationship definition is not reflexive.
ENT class’s mv_credit_card_no attribute in a method called buy_toys(). Since mv_ For example, it would not be possible for class LCL_PARENT to access the private
credit_card_no is defined as a private attribute, the only way for LCL_CHILD to components of class LCL_CHILD without the LCL_CHILD class granting friendship
access this value is through the friendship relationship. Without this addition, the access to LCL_PARENT first. Secondly, notice that classes cannot arbitrarily declare
code below would produce a syntax error. themselves friends of another class. For instance, it would not be possible for
class LCL_CHILD to surreptitiously declare itself a friend of class LCL_PARENT. If this
CLASS lcl_child DEFINITION DEFERRED.
CLASS lcl_parent DEFINITION FRIENDS lcl_child. were the case, access control would be a waste of time since any class could
PRIVATE SECTION. bypass this restriction by simply declaring themselves a friend of whatever class
DATA mv_credit_card_no TYPE string. they were trying to access.
ENDCLASS.
The example shown in Listing 3.10 also introduced a new addition to the CLASS
CLASS lcl_child DEFINITION.
PUBLIC SECTION. DEFINITION statement that we have not seen before: the DEFERRED addition. In a
METHODS buy_toys. scenario like this, the DEFERRED addition used in the first CLASS DEFINITION state-
ENDCLASS. ment for LCL_CHILD is needed to instruct the compiler of the existence of the LCL_
CLASS lcl_child IMPLEMENTATION.
CHILD class in the CLASS DEFINITION statement for the LCL_PARENT class. Without
METHOD buy_toys.
DATA: lo_parent TYPE REF TO lcl_parent, this clause, the compiler would have complained that class LCL_CHILD was
lo_store TYPE REF TO lcl_toy_store. unknown whenever we tried to establish the friendship relationship in the defi-
lo_parent = ...
nition of class LCL_PARENT.
lo_store = ...
138 139
3 Encapsulation and Implementation Hiding UML Tutorial: Sequence Diagrams 3.5
cept could be adapted into object-oriented software designs in order to improve are initiated by a request message from some kind of external source. In the
the reliability of software components that are “...implementations meant to sat- example in Figure 3.9, the external source is a user interfacing with the ATM
isfy well-understood specifications.” machine. This initial message is called a found message. In object-oriented terms,
a message is analogous to a method call. Messages are sent to objects (depicted in
In this context, objects are subject to a series of invariants (or constraints) that
the familiar object boxes seen on the object diagrams described in Chapter 2). The
specify the valid states for the object. To maintain these invariants, methods are
dashed line protruding from underneath the object box represents the object’s
defined using preconditions (what must be true before the method is executed)
lifeline.
and postconditions (what must be true after the method is executed). In Chapter 8,
we’ll look at ways to deal with exceptions to these rules.
Object
The primary goal when applying the Design by Contract approach in your software Box
designs is to produce components that deliver predictable results. The boundaries
set by the visibility sections ensure that loopholes are not introduced into the con-
tract. For instance, the date library that we first introduced in Section 3.1.2 had serviceBroker:
atm: ATM bank: Bank
ATMServiceBroker
many loopholes that made it possible to bypass the business rules implemented
inside the function module(s). The encapsulation techniques we applied in the Message with
Parameters
class-based reimplementation of this library eliminated these loopholes by encap-
withdraw(amt: money)
sulating the date data as a private attribute that’s cut off from external tampering. hasFunds(acct, amt)
hasFunds(acct, amt)
Client programmers using classes based on these principles know what to expect
Found
from the class based on the provided public interface. Similarly, class developers Message
are free to change the underlying implementation so long as they continue to dispenseCash Lifeline
honor the contract outlined in the public interface. Over time, the duel nature of Activation Self Call
this relationship helps to increase trust as we accumulate reusable modules that Bar
printReceipt Message
clients know will work.
getBalance
getBalance
Return
3.5 UML Tutorial: Sequence Diagrams
balance
So far, our study of the UML has been focused on diagrams that are used to balance
describe the static architecture of an object-oriented system. In this chapter, we
will introduce the first of several behavioral diagrams that are used to illustrate the
behavior of objects at runtime. The sequence diagram depicts a message sequence Figure 3.9 Sequence Diagram for Withdrawing Cash from an ATM
chart between objects that are interacting inside a software system.
Figure 3.9 shows a simple sequence diagram that is used to illustrate a cash with- The intersection of a message and an object’s lifeline is depicted with a thin rect-
drawal transaction in an ATM machine. A sequence diagram is essentially a graph angular box called an activation bar. The activation bar shows when an object is
in two dimensions. The various objects involved in the interaction are aligned active during the interaction. Objects are activated via messages (i.e. method
along the horizontal axis. The vertical axis represents time. Sequence diagrams calls). Messages can include parameters that help clarify the operation to be per-
formed by the object. However, it’s not a good idea to try and fully specify the
140 141
3 Encapsulation and Implementation Hiding
In some cases, a method might need to call other local helper methods to com-
plete its task. In this case, a self call can be illustrated by drawing a circuitous
arrow to another activation bar that is stacked on top of the current activation
bar. For example, in Figure 3.9, messages dispenseCash and printReceipt are
both represented as self calls on the atm object inside method withdraw.
Sequence diagrams are very useful for explaining complex interactions where the
order of operations is difficult to follow. One of the reasons that sequence dia-
grams are so popular is that the notation is very intuitive and easy to read. To
maintain this readability, it’s important to avoid cluttering a sequence diagram
with too many interactions. In the coming chapters, we’ll look at other types of
interaction diagrams that can be used to illustrate fine-grained behavior within an
object or more involved interactions that span multiple use cases.
3.6 Summary
In this chapter, you learned about the many advantages of applying encapsulation
and implementation hiding techniques to your class designs. Encapsulating data
and behavior in classes simplifies the way that users/clients work with classes.
Hiding the implementation details of these classes strengthens the design even
further, making classes much more resistant to change and/or data corruption.
The combination of these two design techniques helps you to design intelligent
classes that are highly self-sufficient. Such classes are easy to reuse in other con-
texts since they are loosely coupled to the outside world.
In the next chapter, we’ll examine the basic lifecycle of an object. We’ll also learn
about special methods called constructors that can be used to ensure that object
instances are always created in a valid state.
142
Contents
Introduction ..................................................................................................... 15
PART I Introduction
7
Contents Contents
8 9
Contents Contents
7 Component-Based Design Concepts ........................................ 233 9 Unit Tests with ABAP Unit ........................................................ 299
7.1 Understanding the SAP Component Model ................................... 233 9.1 ABAP Unit Overview ..................................................................... 300
7.2 The Package Concept .................................................................... 236 9.1.1 Unit Testing Terminology ................................................. 300
7.2.1 Why Do We Need Packages? ........................................... 237 9.1.2 Understanding How ABAP Unit Works ............................. 301
7.2.2 Introducing Packages ....................................................... 238 9.1.3 ABAP Unit and Production Code ...................................... 301
7.2.3 Creating Packages Using the Package Builder ................... 240 9.2 Creating Unit Test Classes .............................................................. 301
7.2.4 Embedding Packages ........................................................ 248 9.2.1 Unit Test Naming Conventions ......................................... 302
7.2.5 Defining Package Interfaces .............................................. 250 9.2.2 Test Attributes ................................................................. 303
7.2.6 Creating Use Accesses ...................................................... 253 9.2.3 Test Methods ................................................................... 304
7.2.7 Performing Package Checks .............................................. 254 9.2.4 Managing Fixtures ............................................................ 305
7.2.8 Restriction of Client Packages ........................................... 256 9.2.5 Test Class Generation Wizard ........................................... 306
7.3 Package Design Concepts .............................................................. 258 9.2.6 Global Test Classes ........................................................... 307
7.4 UML Tutorial: Package Diagrams ................................................... 260 9.3 Assertions in ABAP Unit ................................................................ 307
7.5 Summary ....................................................................................... 262 9.3.1 Creating and Evaluating Custom Constraints ..................... 308
9.3.2 Applying Multiple Constraints ........................................ 309
10 11
Contents Contents
9.4 Managing Dependencies ............................................................... 310 10.5.2 Processing Transactions .................................................... 370
9.4.1 Dependency Injection ...................................................... 311 10.5.3 Influencing the Transaction Lifecycle ................................ 374
9.4.2 Private Dependency Injection ........................................... 311 10.6 UML Tutorial: Communication Diagrams ....................................... 375
9.4.3 Partially Implemented Interfaces ...................................... 312 10.7 Summary ....................................................................................... 377
9.4.4 Other Sources of Information ........................................... 312
9.5 Case Study: Creating a Unit Test in ABAP Unit ............................... 313
11 Business Object Development with the BOPF ......................... 379
9.6 Executing Unit Tests ...................................................................... 316
9.6.1 Integration with the ABAP Workbench ............................. 316 11.1 What is the BOPF? ........................................................................ 379
9.6.2 Creating Favorites in the ABAP Unit Test Browser ............ 317 11.2 Anatomy of a Business Object ....................................................... 382
9.6.3 Integration with the Code Inspector ................................. 318 11.2.1 Nodes .............................................................................. 383
9.7 Evaluating Unit Test Results ........................................................... 319 11.2.2 Actions ............................................................................. 387
9.8 Moving Towards Test-Driven Development ................................... 321 11.2.3 Determinations ................................................................ 389
9.9 Behavior-Driven Development ....................................................... 322 11.2.4 Validations ....................................................................... 391
9.10 UML Tutorial: Use Case Diagrams .................................................. 323 11.2.5 Associations ..................................................................... 392
9.10.1 Use Case Terminology ...................................................... 323 11.2.6 Queries ............................................................................ 396
9.10.2 An Example Use Case ....................................................... 324 11.3 Working with the BOPF Client API ................................................ 397
9.10.3 The Use Case Diagram ...................................................... 326 11.3.1 API Overview ................................................................... 397
9.10.4 Use Cases for Requirements Verification ........................... 327 11.3.2 Creating BO Instances and Node Rows ............................. 401
9.10.5 Use Cases and Testing ...................................................... 327 11.3.3 Searching for BO Instances ............................................... 404
9.11 Summary ....................................................................................... 328 11.3.4 Updating and Deleting BO Node Rows ............................ 405
11.3.5 Executing Actions ............................................................. 406
11.3.6 Working with the Transaction Manager ............................ 407
PART II Case Studies 11.4 Where to Go From Here ................................................................ 408
11.4.1 Looking at the Big Picture ................................................ 409
10 ABAP Object Services ................................................................ 331 11.4.2 Building and Enhancing BOs ............................................. 410
10.1 Introduction .................................................................................. 331 11.4.3 Finding BOPF-Related Resources ...................................... 410
10.1.1 Understanding Object-Relational Mapping (ORM) 11.5 UML Tutorial: Advanced Sequence Diagrams ................................. 411
Concepts .......................................................................... 332 11.5.1 Creating and Deleting Objects .......................................... 412
10.1.2 Services Overview ............................................................ 333 11.5.2 Depicting Control Logic with Interaction Frames .............. 412
10.2 Working with the Persistence Service ............................................ 335 11.6 Summary ....................................................................................... 413
10.2.1 Introducing Persistent Classes .......................................... 335
10.2.2 Mapping Persistent Classes ............................................... 340 12 Working with the SAP List Viewer ........................................... 415
10.2.3 Working with Persistent Objects ...................................... 352
10.3 Querying Persistent Objects with the Query Service ...................... 357 12.1 What is the SAP List Viewer? ......................................................... 415
10.3.1 Technical Overview .......................................................... 358 12.2 Introducing the ALV Object Model ................................................ 418
10.3.2 Building Query Expressions .............................................. 359 12.3 Developing a Reporting Framework on top of ALV ........................ 421
10.4 Modeling Complex Entity Relationships ......................................... 362 12.3.1 Step 1: Identifying the Key Classes and Interfaces ............. 422
10.4.1 Performing Reverse Lookups ............................................ 362 12.3.2 Step 2: Integrating the Framework into an
10.4.2 Navigating N-to-M Relationships ..................................... 364 ABAP Report Program ...................................................... 424
10.5 Transaction Handling with the Transaction Service ......................... 369 12.3.3 Step 3: Creating Custom Report Feeder Classes ................ 425
10.5.1 Technical Overview .......................................................... 369
12 13
Contents
Appendices........................................................................................ 437
A Installing the Eclipse IDE .......................................................................... 439
A.1 Installing the Java SDK .................................................................. 439
A.2 Installing Eclipse ............................................................................ 440
A.3 Installing the ABAP Development Tools ......................................... 442
A.4 Where to Go to Find Help ............................................................. 445
B Debugging Objects .................................................................................. 447
B.1 Understanding Debugger Types ..................................................... 447
B.2 Debugging Objects Using the Classic Debugger ............................. 447
B.2.1 Displaying and Editing Attributes ..................................... 447
B.2.2 Tracing Through Methods ................................................ 449
B.2.3 Displaying Events and Event Handler Methods ................. 450
B.2.4 Viewing Reference Assignments for an Object .................. 451
B.2.5 Troubleshooting Class-Based Exceptions ........................... 452
B.3 Debugging Objects Using the New Debugger ................................ 455
C Bibliography ............................................................................................. 459
D The Authors ............................................................................................. 461
Index................................................................................................................. 463
14
Index
463
Index Index
BOPF (Cont.) Class-based exception handling concept, 263 Constructors (Cont.) Events (Cont.)
updating BO instances, 405 exception classes, 266 defining class constructors in local classes, 151 registering event handler methods, 70
validations, 391 prior approaches, 263 defining instance constructors in global relevant abap syntax, 69
BOPF business object resumable exceptions, 290 classes, 149 usage scenario, 68
nodes, 383 the TRY control structure, 266 defining instance constructors in local classes, Exception classes, 263
Business application programming interface Classes, 26 148 constructor method, 272
BAPI, 125 attributes, 50 guaranteed initialization, 148 CX_DYNAMIC_CHECK, 269
Business object layer class attributes, 50 instance constructor behavior example, 149 CX_NO_CHECK, 269
BOL, 382 class components, 49 CREATE OBJECT statement, 60 CX_STATIC_CHECK, 269
Business object processing framework comparison with type declarations, 27 defining exception texts, 273
BOPF, 379 component declarations, 49 global exception class example, 271
Business server pages constants, 51 D global exception classes, 270
BSPs, 422 declaration section, 47 mapping exception texts to message classes,
declaring types, 56 Data objects 274
defining a local class, 82 dynamic data objects, 147 types, 268
C defining in ABAP, 47–48 dynamic type, 206 Exception handling
encapsulation, 131 Data transfer object message table parameters, 265
CALL METHOD statement, 64 events, 56 DTO, 156 Exception texts, 273
CAST operator, 209 global classes, 84 Debugging objects as constants, 273
Casting, 207 implementation section, 47 always create exception object option, 452 text parameters, 274
casting operator (?=), 209 instance attributes, 50 Dependency injection, 311, 313 Exceptions
dynamic types, 206 instance components, 49 partially implemented interfaces, 312 exception classes with message classes, 271
narrowing cast, 207 introduction, 27 private dependency injection, 311 non-classed-based exceptions, 265
narrowing cast example, 207 methods, 52 Design patterns, 434 the exception builder tool, 270
widening cast, 208 naming conventions, 48 reference materials, 434 the RAISE EXCEPTION statement, 283
CATCH statement, 266 template analogy, 28 Design-by-contract, 139 Extended program check
best practices for using, 278 visibility sections, 33 invariants, 140 transaction SLIN, 256
Class Builder Classes and objects postconditions, 140
defining inheritance relationships, 170 relationship, 28 preconditions, 140
exception builder view, 270 Classic debugger tool, 447 Development classes, 236 F
form-based editor, 88 CLEANUP statement, 266 Development packages, 239
local definitions / implementations, 95 usage example, 281 Dynamic method call binding, 210 Factory pattern
mapping assistant tool, 340 Common closure principle, 258 Dynamic object allocation defined, 156
source code editor, 96 Common reuse principle, 258 performance costs, 143 Final classes, 188
transaction SE24, 85 Composition, 34, 165 Final keyword, 183
Class components defined, 193 Final methods, 189
accessing, 67 the ‘has-a’ relationship, 192 E Floorplan manager
CLASS DEFINITION statement COND statement, 285 FPM, 423
DEFERRED addition, 139 Constructor expressions, 115 Eclipse, 97 FPM-BOPF integration
Class diagram conditional operators, 115 history, 97 FBI, 381
example, 39 conversion/casting operators, 115 templates, 107 Friend concept, 137
Class elements instance operator, 115 Encapsulation, 31, 121 Function group, 125
attributes, 26 reference operator, 115 purpose, 133 Function modules, 125
methods, 26 value operator, 115 the 'least privilege' concept, 177 Functional decomposition, 122
Class interface, 29 Constructors, 38 Events, 56 Functional methods
Class pools, 85 class constructor syntax, 151 declaration syntax, 56 changes in release 7.40, 76
CLASS statement defining class constructors in global classes, event handler methods, 69 usage example, 73
INHERITING FROM addition, 169 151 example, 71 usage in ABAP expressions, 75
464 465
Index Index
466 467
Index Index
Polymorphism, 36, 203 SAP support portal, 245 Transaction service (Cont.) UML class diagram (Cont.)
example, 37 SAP Web AS overview, 369 depicting nested and component interfaces,
extensibility, 212 ABAP runtime environment, 143 usage example, 370 229
flexibility, 212 performance optimizations of the ABAP run- TRY Statement generalization notation for interfaces, 229
Procedural programming time environment, 147 Generic CATCH blocks, 279 non-normative notation for abstract classes,
case study, 125 Semantic dissonance, 25 TRY statement, 276 200
lessons learned, 121 Singleton pattern CATCH block, 266, 276 UML communication diagram
Programming languages defined, 154 CLEANUP block, 266 interaction diagrams, 375
assembly language, 24 Software components, 233 defined, 266 notation, 375
C, 24 SOLID design principals, 313 syntax, 266 numbering scheme, 376
evolution, 24 Standard classes Types, 56 relationship to collaboration diagrams, 375
/BOBF/CL_FRW_FACTORY, 399 using in classes, 56 relationship to object diagram, 376
/BOBF/CL_TRA_SERV_MGR_FACTORY, 399 UML diagrams
Q CL_GUI_ALV_GRID, 417 behavioral diagrams, 140
CL_OS_SYSTEM, 358 U interaction diagrams, 142
Query service CL_SALV_HIERSEQ_TABLE, 419 UML package diagram
architecture, 358 CL_SALV_TABLE, 419 UML defining visibility of components, 261
complex query example, 360 Standard interfaces activity diagram, 294, 430 dependency example, 261
overview, 357 /BOBF/IF_FRW_ACTION, 388 advanced class diagrams, 198 dependency notation, 261
query expressions, 359 /BOBF/IF_FRW_ASSOCIATION, 394 advanced sequence diagrams, 411 example, 261
usage overview, 358 /BOBF/IF_FRW_CONFIGURATION, 398 Class Diagram, 38 notation, 261
/BOBF/IF_FRW_DETERMINATION, 389 communication diagrams, 375 packages, 260
/BOBF/IF_FRW_QUERY, 396 object diagrams, 117 relaxed notation, 261
R /BOBF/IF_FRW_VALIDATION, 392 package diagrams, 260 UML sequence diagram
/BOBF/IF_TRA_SERVICE_MANAGER, 397 sequence diagrams, 140 'new' message, 412
RAISE EXCEPTION statement, 282 /BOBF/IF_TRA_TRANSACTION_MGR, 398 state machine diagrams, 161 deleting an object lifeline, 412
behavior, 283 IF_MESSAGE, 278 UML activity diagram found message, 141
syntax, 283 IF_OS_CA_INSTANCE, 340 action, 295 messages, 141
usage example, 284 IF_OS_CA_PERSISTENCY, 340 activity final node, 295 notation, 140
Refactoring IF_OS_CHECK, 374 decision node guards, 432 object activation bar, 141
definition, 195 IF_OS_FACTORY, 340 decision nodes, 432 object lifelines, 141
Refactoring assistant, 195 IF_OS_QUERY, 358 example, 294 self call, 142
Release 7.40 IF_OS_QUERY_MANAGER, 358 expansion region, 295 UML state machine diagram
new syntax features, 114 IF_OS_STATE, 336 handler blocks, 295 final state, 163
Resumable exceptions, 290 IF_OS_TRANSACTION, 369 initial node, 294 initial pseudostate, 161
RESUME statement, 293 Static dependencies principle, 259 joins, 431 notation, 161
Step-wise refinement, 122 merge node, 295 states, 162
Structure packages, 238 notation, 294 transitions, 162
S Subclasses, 173 partitions, 430 UML use case diagram
SWITCH statement, 285 protected nodes, 295 example, 326
SAP application hierarchy, 245 signals, 430 usage, 326
application components, 245 sub-activities, 430 Unified Modeling Language, 23
SAP component model, 233 T time signal, 430 unit test, 299
SAP control framework, 417 UML class diagram Use cases, 323
SAP gateway, 381 Test-driven development, 321 abstract class example, 199 actor, 323–324
SAP list viewer Transaction service composition example, 199 extension scenarios, 324
ALV, 415 check agents, 374 composition notation, 199 extensions, 323
overview, 415 influencing the transaction lifecycle, 374
468 469
Index
X
V
xUnit, 300
Visibility sections, 33, 133
private section, 133
protected section, 176 Z
public section, 133
ZIF_COMPARABLE interface, 215
470
First-hand knowledge.
www.sap-press.com/3597 red, or individual pages be removed. The use for any commercial purpose other than promoting the book is strictly prohibited.