Experiences with DCI pattern Ilona Bluemke1 and Anna Stepień1 1
Institute of Computer Science, Warsaw University of Technology, Nowowiejska 15/19, Warsaw, Poland
[email protected]
Abstract. The DCI architectural pattern for software, introduced by Reenskaug, contains three parts: Data, Context and Interaction. Data represent domain knowledge while Context and Interaction represent the business logic by implementing communication between objects. Context dynamically injects roles into objects. This design pattern is especially appropriate for agile software development. The goal of our paper is to present some practical experiences with the DCI design pattern. We used the DCI pattern in an exemplary application. We proposed and described the association and cooperation between the DCI and MVC (Model View Controller) pattern. Some remarks on the usage of the DCI design pattern in the software development are also given. Keywords: design patterns, DCI, MVC
1
Introduction
In software engineering, a design pattern is a general, reusable solution to a commonly occurring problem within a given context in the software design. A design pattern is not a finished design that can be transformed directly into the source or machine code. It is a description or template for how to solve a problem that can be used in many different situations. Patterns are formalized best practices that the programmer can implement in the application. Patterns originated as an architectural concept by Christopher Alexander (1977/79) [1]. In 1987, Kent Beck and Ward Cunningham began experimenting with the idea of applying patterns to programming and presented their results at the OOPSLA conference [2]. Design patterns gained popularity in computer science after the book Design Patterns: Elements of Reusable Object-Oriented Software was published in 1994 by the so-called "Gang of Four" [3]. In 1995 the Portland Pattern Repository [4] was set up for the documentation of design patterns. Object-oriented design patterns typically show relationships and interactions between classes or objects, without specifying the final application artifacts that are involved [5]. Design patterns reside in the domain of modules and interconnections. At a higher level there are architectural patterns that are larger in scope, usually describing an overall pattern followed by an entire system. There are many types of design patterns, for instance: adfa, p. 1, 2011. © Springer-Verlag Berlin Heidelberg 2011
• Algorithm strategy patterns addressing concerns related to high-level strategies describing how to exploit application characteristics on a computing platform. • Computational design patterns addressing concerns related to key computation identification. • Execution patterns that address concerns related to supporting application execution, including strategies in executing streams of tasks and building blocks to support task synchronization. • Implementation strategy patterns addressing concerns related to implementing source code to support program organization, and the common data structures specific to parallel programming. • Structural design patterns addressing concerns related to high-level structures of applications being developed. Design patterns can speed up the development process by providing tested, proven development paradigms [3, 4, 5]. Effective software design requires considering issues that may not become visible until later in the implementation. Reusing design patterns helps to prevent subtle issues that can cause major problems, and it also improves code readability for programmers and architects who are familiar with the patterns. Meyer and Arnout were able to provide full or partial componentization of two-thirds of the patterns they attempted [6]. In this paper we concentrate on a design pattern which draws attention and discussion for several years called DCI (Data, Context, Interaction). The DCI pattern was introduced in 2008 by Trygve Reenskaug [7, 8, 9, 10] and is being used, elaborated by James O. Coplien and others e.g. [11, 12, 13, 14, 15, 16]. The main idea of DCI is to separate the code that describes the system state from the code that describes the system behavior. The code is organized in three perspectives each of which focuses on a certain aspect of the code, these perspectives are called: • Data - contains the computer representation of the user’s mental model, • Context is the specification of a network of communicating objects that realizes a user command, • Interaction - specifies how objects communicate when executing a user command. The idea of separating what the system is and what it does seemed very interesting to us. In the literature we were able to find only small examples of the DCI usage e.g. for one simple use case, so we decided to implement a case system. Our contribution is the usage of the DCI paradigm in the system, called DCI –Project, which we designed and implemented. We also present how DCI and MVC (Model View Controller) [17] patterns can be combined in the architecture of the system (section 4.1). In this paper we present some of our experiences gathered during the development of our system. The organization of our paper is as follows. Firstly, we describe briefly the DCI concept and related work (section 3). In section 4 we introduce our system and give an example. Finally, section 5 contains some concluding remarks.
2
DCI
Applying the DCI pattern we should view the program in three perspectives: 1. Data, 2. Context, 3. Interaction. In the Data perspective the conceptual schema is coded as a set of class definitions. The only methods that are in these classes are data access methods and methods for derived attributes. The data classes are instantiated to form an object structure that corresponds to the conceptual schema of the user’s mental model. The system behavior is the system’s response to user commands. A user command starts a method in one of the objects. This method sends further messages to other objects so that several objects communicate to execute the command. In the DCI program, communicating objects are coded as a network of connected roles. The establishment and maintenance of the runtime network structure is centralized in an element called the Context. Context is a class specifying a network of communicating objects as a similar structure of roles and connectors. It specifies also methods that bind roles to objects at the runtime. Interaction specifies how objects interact to realize a system operation expressed in terms of its roles. All objects that play a given role shall process the same interaction messages with the same methods. These methods are called role methods and are properties of the role. The role methods are injected into the data classes, and the classes may not override them. In Figure 1 the DCI paradigm is presented with an injection relation from role to class. The instances of these classes will give priority to the role methods above any methods defined in the class itself.
Fig. 1. DCI paradigm –source [8]
The Context object is encapsulated and its inner contents is invisible from the outside so it can be anything. The role abstraction describes how the object is used together with other objects while the class abstraction describes the inner construction of an object. Data classes constitute objects that interact to implement system operations. Object interaction takes place within a Context where the objects are identified by the Roles they play. Objects are “temporarily equipped” with role methods while they are playing a role. As the role methods are associated with the roles rather than with classes we can reason about system operations without having to study the classes of the roleplaying objects.
3
Related work
The idea of DCI is very interesting and it seems that this pattern could be very useful and convenient in the software development especially with Lean [18] architecture or Agile development [18]. Since its inception the DCI approach has spread in many languages such as Ruby, Python, C++, C#, Java and many more. In strongly dynamic languages like Ruby or Python, a context can dynamically inject roles into an object so the implementation of DCI in these languages is easy and natural. More implementation problems occur in Java and C++. In [19] we presented how to efficiently implement DCI in these languages. As the examples available in the literature present usually partial code (e.g. [20]), also only very simple examples can be found in blogs on DCI e.g. [21, 22, 23] so several researchers decided to check the real usefulness of this pattern in a case project. We also found the available examples unsatisfactory and designed and developed an exemplary project using the DCI paradigm, presented in section 4. When we started our project (in 2011) the works described below were not published yet. Hasso and Carlson [24] in 2013 introduced a conceptual framework and an implementation model for software composition using the DCI architecture. Theirs compositional model is based on design patterns by abstracting behavioral model using role modeling constructs. They describe how to transform a design pattern into a role model that can be used to assemble a software application. Theirs approach offers a complete, practical design and implementation strategies, adapted from DCI (Data, Context, and Interaction) architecture. They demonstrate this technique by presenting a simple case study, system RESORT, implemented in C# language. They also created a process that should guide practitioners and students, learning how to use design patterns, in assembling individual components created by different teams. Qing and Zhong in 2012 [20] proposed a “seamless software development approach using DCI”. They use a method based on Problem Frame to capture the requirements and DCI for software architecture. Problem frame is a software requirement method proposed by Jackson [25, 26] and provides a schema for analyzing and decomposing problems. The Problem Frame has five patterns: Demand behavior frame, Command behavior frame, Information display frame, Simple tools frame, and Transformation frame. Qing and Zhong observed that DCI architecture and Problem
frame have a similar vision how to construct programs. DCI can capture the end user cognitive model of roles and interactions between them. They integrate Problem Frame and DCI and claim that such approach enables to develop the software seamlessly. Hayata, Han and Beheshti in 2012 [27] proposed a framework showing how agile practices could be fulfilled by introducing “lean” practices under the DCI paradigm. In the proposed framework, the lean architecture is complementary to agile principles and supports the agile development. The DCI approach is the backbone for lean architecture. Developers separate “what-the-system-is” (domain) from “what-the systemdoes” (business-logic features). This separation of rapidly changing features from the stable domain architecture enables developers to focus on coding fast with confidence rather than do several iterations. Lean architecture achieves consistency by applying the DCI approach, allowing developers to separate the long-term structure of domain from its rapidly changing features.
4
System based on DCI paradigm
The idea behind DCI looks promising and it seems that this pattern could be very useful and convenient in the software development, especially combined with Lean architecture or Agile development [18]. We decided to check the real usefulness of this pattern on an exemplary project. Similar approach was used by others and theirs systems are mentioned in section 3. We designed and developed an application named DCI-Project. The detailed description is given in [28]. The main goal of DCI – Project is the management of projects, tasks and documents. It can be used by a group of people working on several projects. It enables to create, edit, delete, view projects. The actors of this application are: user, collaborator and project owner. The project owner (project manager) can create tasks and assign them to staff members. Users of this system can also monitor some items (tasks or projects) and comment them. The use case diagram for a project owner is given in Fig. 3. DCI-Project was written in Ruby [29] with the usage of Ruby on Rails [30] framework. We started with the use case model as a ”driving force” to implement the application. The architecture of the DCI-Project comprises of the Data part which describes the core of the system and the Interaction part which describes system’s functionality. The third element – Context dynamically connects these parts. We have objects to represent the applications’ domain objects; roles and their methods to represent system behavior and contexts to represent use cases – interactions between roles. The architecture of the application makes a clear distinction between design activities corresponding to each of the artifacts namely the Data, Context, and Interaction. It also makes traceability between what the user wants and where it is implemented in the code clear through the context construct in the architecture. The domain object knows everything about its state and how to maintain it. Coplien refer to these domain objects as dumb objects that know nothing about other objects in the system. The interaction between domain objects is a system functionality captured as the system behavior and assigned to Interaction objects. In a typical use case scenario system
entities interact with each other through defined roles. These roles will be assigned to domain objects instantiated at the runtime. At the design time these object roles and the expected behavior should be identified. System functionality i.e. functionality that does not belong to any specific object type at design time is injected into objects at the runtime.
Fig. 3. Use case diagram for Project owner
4.1
DCI and MVC
Analyzing DCI we may have some associations with the MVC (Model View Controller) [17]. MVC was also introduced by Trygve Reenskaug but in the 1970s in Smalltalk. In late eighties this concept became popular in object technology initially in the development of graphical user interfaces, currently is being used in different parts of system. MVC divides a software application into three interconnected parts so internal representations of information is separated from the ways that information is presented to the user. The central component (Model) consists of application data, logic and functions. A View can be any output representation of information such as a chart or a diagram. Multiple views of the same information are possible e.g. bar chart and a table. The third part - Controller accepts input and converts it to commands for the model or view. Our exemplary system (the DCI Project) was implemented in Ruby on Rails framework [30] which imposed the usage of MVC. We have to combine the MVC and the DCI in the architecture of our system. In Fig. 4 the architecture of the DCI Project is shown. As the Model in MVC is responsible for data it was obvious that it contains Data (from DCI). Controller in MVC is responsible for the logic and is the central part of the application. Similar is the role of Context (in DCI) so these two perspectives are combined. In Controller the context classes are being executed. The
difference of this architecture compared to the classical MVC implementation is that the Controller does not have direct access to data. The communication Controller – Data is performed trough Context.
Fig. 4 DCI and MVC in DCI- Project application
MVC (Model View Controller) nowadays widely used pattern and DCI are complementary. MVC transforms the data into a physical form while DCI creates a program that represents the human mental model. The two patterns meet when MVC is used to bridge the gap between the human mind and the model implied by the DCIbased computer system. 4.2
Exemplary code
In Fig. 3 one of use case diagrams from our application DCI-Project is shown. The implementation of one use case from it i.e. “changing the project owner” is presented in Fig. 5. The code was written using DCI paradigm principles. In the application each use case is represented by a separate context. Such separation allows contexts to be reusable and easy to maintain. 1.class ChangeProjectOwnerContext 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
include Context def initialize(project_owner, system_user, project_id) role ProjectOwner, project_owner role SystemUser, system_user @project_id = project_id end def execute interaction do
12.
project = ProjectOwn
r.change_ownership_of_project(@project_id) 13. Response.new(project) 14. end 15. end 16. module SystemUser 17. extend Role 18. class