A Class Type Architecture For Layering Your Application
A Ronin International White Paper
by Scott W. Ambler, Senior Consultant, Ronin International
Table of Contents
- Introduction
- The User Interface Layer
- The Control/Process Layer
- The Business/Domain Layer
- The Persistence Layer
- The System Layer
- Implications for Modeling
- Summary
- Definitions
- Source
- References
Layering is a technique that supports the concept of separation of concerns by organizing your software design into layers/collections of classes or components that fulfill a common purpose, such as implementing your user interface or the business logic of your system. A class-type architecture (Ambler 2001a; Ambler 1997) provides a strategy for layering the classes of your software to distribute the functionality of your software among classes. Furthermore, class-type architectures provide guidance as to what other types of classes a given type of class will interact with, and how that interaction will occur. This increases the extensibility, maintainability, and portability of the systems you create.
What are the qualities that make up good layers? First, it seems reasonable that you should be able to make modifications to any given layer without affecting any other layers. This will help to make our system easy to extend and to maintain -- in other words more flexible and robust. Second, layers should be modularized. You should be able either to rewrite a layer or simply replace it and, as long as the interface remains the same, the rest of the system should not be affected. This will help to make increase the portability of your software. Third, layers should be cohesive: they should encapsulate one high-level concept. A cohesive layer is easier to understand, and thus to work with.
Figure 1 depicts a five-layer class-type architecture for the design of object-oriented software. As the name suggests, a user interface (UI) class implements a major UI element of your system. The business behavior of your system is implemented by two layers: business/domain classes and controller/process classes. Business/domain classes implement the concepts pertinent to your business domain such as “student” or “seminar,” focusing on the data aspects of the business objects, plus behaviors specific to individual objects. Controller/process classes, on the other hand, implement business logic that involves collaborating with several business/domain classes or even other controller/process classes. Persistence classes encapsulate the capability to store, retrieve, and delete objects permanently without revealing details of the underlying storage technology. Finally, system classes provide operating-system-specific functionality for your applications, isolating your software from the operating system (OS) by wrapping OS-specific features, increasing the portability of your application.
Collaboration between classes is allowed within a layer, for example, UI classes can send messages to other UI classes and business/domain classes can send messages to other business/domain classes. Collaboration can also occur between classes in layers connected by arrows. As you see in Figure 1, user interface classes may send messages to business/domain classes, but not to persistence classes. Business/domain classes may send messages to persistence classes, but not to user interface classes. By restricting the flow of messages to only one direction, you dramatically increase the portability of your system by reducing the coupling between classes. For example, the business/domain classes don’t rely on the user interface of the system, implying that you can change the interface without affecting the underlying business logic. All types of classes may interact with system classes. This is because your system layer implements fundamental software features such as inter-process communication (IPC), a service classes use to collaborate with classes on other computers, and audit logging, which classes use to record critical actions taken by the software. For example, if your user interface classes are running on a personal computer (PC) and your business/domain classes are running on an Enterprise JavaBean (EJB) application server on another machine, then your UI classes will send messages to the business/domain classes via the IPC service in the system layer. This service is often implemented via the use of middleware.
Figure 1. The layers of the class type architecture.
A user interface class contains the code for the user interface part of an application. For example, a graphical user interface (GUI) will be implemented as a collection of menu, editing screen, and report classes. Don’t lose sight of the fact that not all applications have GUIs, however. For example, integrated voice response (IVR) system using telephone technology are common, as are Internet-based approaches. Furthermore, by separating the user interface classes from the business/domain classes, you are now in a position to change the user interface in any way you choose.
Consider a university where users currently interact with the system through an existing GUI application. It seems reasonable that people should also be able to interact with the system, perhaps find out information about seminars or even enroll in seminars, over the phone or the Internet. To support these new access methods, you should only have to add the appropriate user interface classes. Although this is a dramatic change in the way the university interacts with its customers (students), the fundamental business has not changed, therefore, you shouldn’t have to change your business/domain classes. The point to be made here is the user interface for any given system can take on many possible forms, even though the underlying business is still the same. The only thing changing is the way you interact with that business functionality.
User interface classes are often identified are part of your UI prototyping efforts, sequence modeling, and user interface flow diagramming. Figure 2 presents a UI flow diagram, also known as a storyboard, for a portion of the university system's user interface.
Figure 2. A User Interface Flow Diagram.
The purpose of a controller/process class is to implement business logic that pertains to several objects, particularly objects that are instances of different classes. Controller classes are there not just because they access several objects; any class might do that. Rather, they represent a business process that cuts across many business concepts, often a business process described by a portion of a use case or a usage scenario. You don't want to put this business logic in your domain classes because it makes them too highly coupled. Furthermore, these classes are typically transient whereas business classes are typically persistent.
Figure 3 depicts a use case for the university system and Figure 4 a UML sequence diagram representing the logic of the basic course of action. Notice the use of stereotypes:
- Controller classes are given the stereotype of “<<controller>>” although you may also often seen “<<controller class>>” applied as well (Jacobson, Booch, & Rumbaugh, 1999)
- User interface classes are assigned the stereotype <<UI>>
- Business/domain classes are not assigned a stereotype
The controller class, “EnrollInSeminar,” only manages interactions between business classes. Notice how this the message flow rules, indicated by Figure 1 . For example, the only types of classes that interact with user interface classes are other user interface classes. The controller classes should just implement business logic and therefore not interact with your UI classes, increasing their portability and reusability. Similarly, business classes should have no knowledge of the UI. Taking a layered approach your design is more robust. It is interesting to note that the controller class destroys itself at the end because it is no longer needed: it completes its job and is discarded afterwards.
Figure 3. The Enroll in Seminar use case.
Enroll in Seminar
Enroll an existing student in a seminar for which she is eligible.
Preconditions:
The Student is registered at the University.
Postconditions:
The Student will be enrolled in the course she wants if she is eligible and room is available.
Basic Course of Action:
1. The student wants to enroll in a seminar.
2. The student inputs his name and student number into the system via “UI23 Security Login Screen.”
3. The system verifies the student is eligible to enroll in seminars at the university, according to business rule “BR129 Determine Eligibility to Enroll.”
4. The system displays “UI32 Seminar Selection Screen,” which indicates the list of available seminars.
5. The student indicates the seminar in which he wants to enroll.
6. The system validates the student is eligible to enroll in the seminar, according to the business rule “BR130 Determine Student Eligibility to Enroll in a Seminar.”
7. The system validates the seminar fits into the existing schedule of the student, according to the business rule “BR143 Validate Student Seminar Schedule.”
8. The system calculates the fees for the seminar based on the fee published in the course catalog, applicable student fees, and applicable taxes. Apply business rules “BR 180 Calculate Student Fees” and “BR45 Calculate Taxes for Seminar.”
9. The system displays the fees via “UI33 Display Seminar Fees Screen.”
10. The system asks the student whether he still wants to enroll in the seminar.
11. The student indicates he wants to enroll in the seminar.
12. The system enrolls the student in the seminar.
13. The system informs the student the enrollment was successful via “UI88 Seminar Enrollment Summary Screen.”
14. The system bills the student for the seminar, according to business rule ‘BR100 Bill Student for Seminar.”
15. The system asks the student if he wants a printed statement of the enrollment.
16. The student indicates he wants a printed statement.
17. The system prints the enrollment statement “UI89 Enrollment Summary Report.”
18. The use case ends when the student takes the printed statement.
Alternate Course A: The Student is Not Eligible to Enroll in Seminars
A.3. The system determines the student is not eligible to enroll in seminars.
A.4. The system informs the student she is not eligible to enroll.
A.5. The use case ends.
Alternate Course B: The Student Does Not Have the Prerequisites
B.6. The system determines the student is not eligible to enroll in the seminar she has chosen.
B.7. The system informs the student she does not have the prerequisites.
B.8. The system informs the student of the prerequisites she needs.
B.9. The use case continues at Step 4 in the basic course of action.
Alternate Course C: The Student Decides Not to Enroll in an Available Seminar
C.4. The student views the list of seminars and doesn’t see one in which he wants to enroll.
C.5. The use case ends.
|
Figure 4. Sequence diagram for the basic course of action for the Enroll In Seminar use case.
A business/domain class, also called an analysis or entity class (Jacobson, Booch, & Rumbaugh, 1999), is a class that encapsulates a single, cohesive business concept. Your subject matter experts (SMEs) are often the people who identify these classes or, at least, the concrete business/domain classes. Figure 5 depicts a conceptual class model that depicts business/domain classes pertinent to a university information system. The business layer enables you to encapsulate the basic business functionality without having to concern yourself with user interface, data management, or system management issues.
Figure 5. A (Partial) Conceptual Class Model for a University.
The persistence layer provides the infrastructure for the storage and retrieval of objects. This helps to isolate your application from changes to your permanent storage approach. You might decide to install the latest version of your database, change your existing database schema, migrate to a new database vendor, or even change your data storage approach completely (perhaps migrating from a relational database to an object database). Regardless of how your persistence strategy changes, your applications should not be affected. The persistence layer, by encapsulating data management functionality, increases the maintainability, extensibility, and portability of your applications.
In the layered class-type architecture of Figure 1, messages flow from the business/domain class layer to the persistence class layer. These messages take the form of “create a new object,” “retrieve this object from the database,” “update this object,” or “delete this object.” These types of messages are referred to as object-oriented create, retrieve, update, and delete (OOCRUD). Another essential concept here is the persistence layer only provides access to permanent storage; it is not the permanent storage mechanism itself. For example, the persistence layer may encapsulate access to a relational database, but it is not the database itself. The goal of the persistence layer is to reduce the maintenance effort that is required whenever changes are made to your database. Why do you need a persistence layer? You know your database will be upgraded. You know tables will be moved from one database to another, or from one server to another. You know your data schema will be changed. You know field names will be changed. The implication is clear: because the database is guaranteed to change, we need to encapsulate it to protect ourselves from the change. A persistence layer is the best way to do this because it minimizes the effort required to handle changes to permanent storage. For more about persistence layers/frameworks, read the white paper The Design of A Robust Persistence Layer.
Every operating system offers functionality that we want to be able to access in our applications -- file handling, multitasking, multithreading, and network access to name a few. It also includes utility classes such as collections and services such as transaction control. Most operating systems offer these features, albeit in slightly different manners. Although many people find this little fact to be worthy of great debate and, perhaps, it actually is, the real issue is the differences between operating systems can make it tough if you are writing an application that needs to work on many different platforms. You want to wrap the features of an operating system in such a way that when you port an application, you only need to modify a minimum number of classes. In other words, you need to create classes that wrap specific features of the operating system. Even if you don’t intend to port your applications to other operating systems, you still need to consider wrapping system functionality. The reason for this is simple: operating systems constantly get upgraded. Every time an upgrade occurs, there are always changes to the way that functionality is currently being offered, including issues such as bug fixes and completely new ways to do things.
The key concept here is wrapping (Ambler 1997). System classes for the most part encapsulate non-OO functionality that we need to make accessible to objects within an application. It is quite common to wrap a series of related operating system calls to provide a related set of functionality. A perfect example would be the file stream classes commonly found in Java and C++. When you look into the inner workings of these classes, you find their methods make specific file-handling calls to the operating system. These classes, particularly the Java ones, provide a common way to work with files, regardless of the platform. Message flow for system classes is greatly restricted. System classes are only allowed to send messages to other system classes, even though each type of class is allowed to send messages to system classes. This is because system classes are the lowest common denominator in software development. This means they don’t need to know anything about the business logic or user interface logic to do their job. Actually, it is not completely true that system classes don’t interact with non-system classes. The use of callbacks, when one object passes itself as a message parameter to another so the receiver can later call it back, is permitted (it is allowed between all layers, but it is most common with system classes). For example, instead of waiting, a business class may request that a printing system class inform it when/if the print request was successful. When the printing is complete, a message would be sent from the system object to the business object informing it of success.
An interesting question to ask is what types of modeling artifacts would you consider using to explore each layer? Table 1 lists potential modeling artifacts, such as use cases or data models, that you may decide to create when you are building each layer. This list is meant to be suggestive, not definitive -- you may choose to create none, some, all, or different models than what is suggested. For a description of each artifact, refer to the essay Artifacts for Agile Modeling: The UML and Beyond posted at the Agile Modeling web site.
As you can see with respect to modeling there is overlap between several of the layers, which is what you would expect. Furthermore the potential models for the Controller/Process and Business/Domain layers are very similar, indicating that the required skillset for these two layers are similar. The models for the user interface layer and the system layer have very little overlap, indicating that the skills needed to develop user interfaces are different than those needed to develop good system software -- not that this should come as a surprise to anyone. The implication is that developers may choose to specialize in the development of classes pertaining to one or two layers.
Table 1. Potential models for each layer.
Layer |
Model |
User Interface |
- Constraint definition
- Essential use case
- Essential user interface prototype
- Feature
- Robustness diagram
- System use case
- Usage scenario
- User interface flow diagram
- User interface prototype
- User story
|
Controller/Process |
- Activity diagram
- Business rule definition
- Constraint definition
- Data flow diagram
- Essential use case
- Feature
- Flow chart
- Robustness diagram
- Sequence diagram
- Specification language
- State chart diagram
- System use case
- Table
- Usage scenario
- Use case diagram
- User story
- Workflow diagram
|
Business/Domain |
- Business rule definition
- Class diagram
- CRC model
- Constraint definition
- Essential use case
- Feature
- Flow chart
- Organization chart
- Robustness diagram
- Sequence diagram
- Specification language
- State chart diagram
- System use case
- Table
- Usage scenario
- Use case diagram
- User story
- Workflow diagram
|
Persistence |
- Class diagram
- Physical data model
|
System |
- Class diagram
- CRC model
- Constraint definition
- Deployment diagram
- External interface specification
- Flow chart
- Network diagram
- Sequence diagram
- Structure diagram
- Technical requirement
|
This white paper presented the five-layer class type architecture of Figure 1 for organizing the design of your object-oriented applications. It described each layer in detail and provided a brief example of building a portion of a business application that conforms to this layered architecture. An overview of the types of artifacts that you may wish to create when you are modeling each layer, models that you may wish to create following an Agile Modeling (AM) approach.
Audit logging. The recording of information to identify an action of interest to the system, when the action took place, and who/what took the action.
Business/domain class. Implement the concepts pertinent to your business domain, such as “customer” or “product.” Business/domain classes are usually found during the analysis process. Although business/domain classes often focus on the data aspects of your business objects, they will also implement methods specific to the individual business concept.
Callback. An approach where one object indicates it wants to be sent a message once its request has finished processing, in effect, it wants to be “called back.”
Class-type architecture. A defined approach to layering the classes that comprise the software of a system. The interaction between classes is often restricted based on the layer to which they belong.
Controller/process class. Implement business logic that involves collaborating with several business/domain classes or even other controller/process classes.
Extensibility. A measure of how easy it is to add new features to, to extend, existing software. If item A is easier to change that item B, then we say that item A is more extensible than item B.
Graphical user interface (GUI). A style of user interface composed of graphical components, such as windows and buttons.
Inter-process communication (IPC). The act of having software running on two separate pieces of hardware interact with one another.
Layering. The organization of software collections (layers) of classes or components that fulfill a common purpose.
Major user interface element A large-grained item, such as a screen, HTML page, or report.
Maintainability. A measure of how easy it is to add, remove, or modify existing features of a system. The easier a system is to change, the more maintainable we say that system is.
Object database (ODB).A permanent storage mechanism, also known as an objectbase or an object-oriented database management system (OODBMS), which natively supports the persistence of objects.
OOCRUD Object-oriented create, retrieve, update, and delete.
Permanent storage Any physical medium to which data can be saved, retrieved, and deleted. Potential permanent storage mechanisms for objects include relational databases, files, and object databases.
Persistence class. Provide the capability to store objects permanently. By encapsulating the storage and retrieval of objects via persistence classes, you are able to use various storage technologies interchangeably without affecting your applications.
Portability. A measure of how easy it is to move an application to another environment (which may vary by the configuration of either their software and hardware). The easier it is to move an application to another environment, the more portable we say that application is.
Relational database (RDB) A permanent storage mechanism in which data is stored as rows in tables. RDBs don’t natively support the persistence of objects, requiring the additional work on the part of developers and/or the use of a persistence layer.
Sequence diagram A UML diagram that models the sequential logic, in effect, the time ordering of messages between objects.
Stereotype Denotes a common use of a modeling element. Stereotypes are used to extend the UML in a consistent manner.
System class. Provide operating-system-specific functionality for your applications or they wrap functionality provided by other tool/application vendors. System classes isolate your software from the operating system (OS), making your application portable between environments, by wrapping OS specific features.
User interface class. A class that provides the capability for users to interact with the system. User interface classes typically define a graphical user interface for an application, although other interface styles, such as voice command or HTML, are also implemented via user-interface classes.
User interface-flow diagram A diagram that models the interface objects of your system and the relationships between them; also known as an interface-flow diagram, a windows navigation diagram, or an interface navigation diagram.
Wrapper A collection of one or more classes that encapsulates access to non-OO technology to make it appear as if it is OO.
Wrapping The act of encapsulating non-OO functionality within a class, making it look and feel like any other object within the system.
The majority of the material for this white paper was modified from Chapter 7 of The Object Primer 2/e. For more information about this book, read the Ronin International white paper The Object Primer -- An Introduction to Techniques for Agile Modeling.
The material regarding implications for modeling was motivated by similar material presented in Chapter 3 of Building Object Applications That Work.
11. References and Recommended Reading
- Ambler, S.W. (1997). Building Object Applications That Work: Your Step-By-Step Handbook for Developing Robust Systems with Object Technology. New York: Cambridge University Press. www.ambysoft.com/buildingObjectApplications.html
-
Ambler, S.W. (2001a). The Object Primer 2nd Edition: The Application Developer’s Guide to Object Orientation. New York: Cambridge University Press. www.ambysoft.com/theObjectPrimer.html.
-
Ambler, S.W. (2001b). Enterprise Unified Process White Paper. ronin-intl.com/publications/unifiedProcess.htm
-
Ambler, S.W. (2001c). Agile Modeling Home Page. www.agilemodeling.com
- Jacobson, I., Booch, G., and Rumbaugh, J. (1999). The Unified Software Development Process. Reading, MA: Addison Wesley Longman, Inc.
Ronin International, Inc. continues to help numerous organizations to learn about and hopefully adopt agile techniques and philosophies. We offer both consulting and training offerings. In addition we host several sites - Agile Modeling, Agile Database Techniques, UML Modeling Style Guidelines, Enterprise Unified Process (EUP) - that you may find of value.
For more information please contact Michael Vizdos at 866-AT-RONIN (U.S. number) or via e-mail ().
|