软件行为模型中的设计模式

简介: 软件行为模型中的设计模式,翻译自ACM杂志,翻译还未结束,原作者持有所有权利

Discovering design patterns in software behavior models

Sandeep Mitra and T. M. Rao

Department of Computing Sciences

The College at Brockport, State University of New York

Brockport, NY 14420

585 395-2234

smitra@brockport.edu

探索软件行为模型中的设计模式

Sandeep Mitra 和 T. M. Rao

纽约州立大学布鲁克波特----计算机科学系

纽约布鲁克波特,邮编14420

(电话):585 395-2234

(邮箱):smitra@brockport.edu

Abstract

The ability to develop extensible [SumiHui1]  and maintainable [SumiHui2]  code is a skill sought by many employers. While students are expected to obtain these skills in software engineering-oriented courses, many small colleges with traditional computer science programs find it challenging to offer multiple courses that cover software engineering concepts [SumiHui3]  in depth [SumiHui4]  . We address this challenge in part by offering a two-course sequence, the first of which teaches the development of high-quality software behavior models using UML sequence diagrams. The second course focuses on the map [SumiHui5]  ping of these models to extensible and maintainable code. In this paper, we describe how discovering design patterns in these models is a key aspect of this mapping process. We assess [SumiHui6]  our approach by evaluating [SumiHui7]  the quality of the code developed in term projects after our techniques were adopted vs. the same in earlier projects [SumiHui8]  . We also describe the results of seeking student reflections [SumiHui9]  on [SumiHui10]   the effectiveness of our approach.

摘要

可扩展性和可维护性代码的开发能力是众多使用者追求的一项技能。当学生期望在面向工程的软件课程里学得这些技能时,许多有着传统的计算机科学技术课程的小学院就发现,要提供多样化的并且全面、深入地涉及软件工程思想的课程,这是一个挑战。我们通过提供一个双课程序列来部分地应对这个挑战,第一个课程教授使用UML序列图进行高质量的软件行为模型的开发;第二个课程的重点是将这些模型映射成可扩展的和可维护的代码。在本文中,我们描述如何在这个映射过程的一个关键方面中发现这些模型中的设计模式。我们以评估早期项目与采用了我们的若干技术后的项目的代码质量的方式来评定我们的方法。我们也描述谋求学生对我们方法有效性的反思结果。

 

 

Introduction

At our institution, software engineering concepts are taught primarily in a two-course sequence, usually taken by students in two successive [SumiHui11]  semesters [SumiHui12]  . A major part of this sequence is a significantly [SumiHui13]  -sized, “real world” project, extending over [SumiHui14]   the two semesters. The project’s requirements are obtained from small local organizations, who are seeking customized [SumiHui15]  software products to execute their day-to-day business processes more efficiently. After deployment, these customers often come back with modification [SumiHui16]  and enhancement [SumiHui17]  requests, which have to be handled by students who are not necessarily the original developers. Therefore, while working on the maintenance exercise that is also part of our two-course sequence, students discover that maintenance is easier if the code is readable, has easily modifiable components and supports easy addition of new components. We have found that being able to identify design patterns that “fit” a certain context [SumiHui18]  and implement them accurately [SumiHui19]  greatly helps in developing such code. Teaching design patterns is a challenge by itself. Students should not use design patterns simply for the sake [SumiHui20]  of using them. Rather, they should have a good idea about the advantages that would accrue [SumiHui21]   from applying a certain pattern in a particular context. This motivates [SumiHui22]  us to search for a suitable technique for teaching design patterns.

介绍

在我们的体系中,软件工程思想主要在一个双课程序列中教授,通常在两个连续的学期里被学生采纳。这个序列一个主要的部分就是把一个有相当数量大小的、真实世界的工程,扩展到两个学期里。这些工程的需求从当地那些正在寻找定制化的软件产品来更高效地完成他们日常商务流程的小组织机构获得。在软件部署到位后,往往这些客户又会带着变更和增加的需求回来,而这些不得不由不一定是最初开发者的学生负责。因此,致力于维护软件使用的这段时间也是我们双课程序列的一部分,学生会发现如果代码有可读性、有易修改的模块组件并且容易支持添加一些新的组件的话,维护起来会更加容易。在开发过程中,我们已经找到这样的代码,能够证明设计模式配合在某一个环境下,能极大地帮助我们准确地实现这一需求。教授设计模式本身就是一个挑战。学生不应该简单地带着为了使用而使用这样的目的而去使用设计模式。准确地说,他们应该清楚的了解在一个特定环境中应用某一个模式所能获得的好处。这促使我们去寻找一种合适的技巧来教授设计模式。

 

In the years after the ‘Gang of Four’ book [4] was first published, many instructors adopted the “catalog approach” to teach design patterns: they simply presented their students with many patterns, explaining for each pattern the context in which it is applicable, an illustrated [SumiHui23]  example problem and the advantages of using the pattern. As described in [6], this approach was not very effective. Alternatively [SumiHui24]  , some instructors sought to present patterns using case [SumiHui25]   studies of ‘killer examples [SumiHui26]  ’ from various domains such as business systems or games [2, 6, 9]. Regardless of the approach used, an important issue to consider is whether students can apply their learning to a problem that is unlike these examples. We realized the importance of this issue in some of our course offerings. For example, in one semester, we provided students with the case studies we normally use – namely [SumiHui27]  , the design and code examples of several rental [SumiHui28]  management systems. But the term project was of a different kind: building a Christmas Tree Sales Management system for a Boy Scout troop [SumiHui29]  . The project had an unfamiliar requirement: only one sales shift [SumiHui30]  should be open at a time. On this basis, students assumed [SumiHui31]  that only one Shift object needs to ever be created, and designed the Shift class as a Singleton. Later on [SumiHui32]  , they realized that the system should also enable [SumiHui33]  incorrectly recorded start and end times of already completed shifts to be modified. This led them to conclude that allowing the creation of only one instance of the Shift class was inappropriate [SumiHui34]  , and they had to rework [SumiHui35]  their code significantly [SumiHui36]  during the “crunch times [SumiHui37]  ” of the semester.

 

 

老早以前,在“四人组(或Gof)”书《设计模式》(Design Patterns: Elements of Reusable Object-Oriented Software)[4]首次发布之后,许多的讲师采用了“目录式方法”来教设计模式:他们简单的向他们的学生展示许多的模式,解释每个模式适用的场景,举一个问题的例子并阐明使用这个模式的优点。根据《Teaching Design Patterns Through Computer Game Development》[6]一书的描述,这个方法不是非常有效。作为一种选择,有些教师从多种领域中寻找能像商务系统或者游戏[2,6,9]一样的能表现模式使用案例的超级有用的例子研究成果。不管使用了怎样的方法,一个需要考虑的重要问题是,学生是否能够将他们所学应用到一个不同于这些例子的问题中。我们意识到了在我们开设的某些课程中这个问题的重要性。例如,在某一个学期里,我们提供给学生一些我们通常使用的研究例子----也就是说,几个租金管理系统的设计和源码例子。但是这个工程里有一种条款:为童子军建立一个圣诞树销售系统。这个工程有一个不常见的需求:一次只有一个销售转换开放。在这个基础上,学生们想当然的认为仅有一个转换对象需要一定被创建,并且将转换类设计成一个单例。后来,他们意识到,该系统还应该能允许对启动和结束的时候已经完成的转换出错记录进行修改。这使得他们得出这样的结论:只允许创建一个转换类的实例是不合适的,他们不得不在这学期的“高压时期”大幅度地修改他们的代码。

 

       Such experiences led us to consider alternative [SumiHui38]  approaches to teaching design patterns. The authors in [1] and [5] advocate [SumiHui39]  that patterns be used as the vehicle [SumiHui40]  to systematically [SumiHui41]  trace [SumiHui42]  well-architected system to code, and realize design principles in code. In this paper, we describe a technique to create software models that show the “bit picture” of system behavior (i.e. [SumiHui43]  , they hide certain details at the high level), but are still created with high precision [SumiHui44]  . We then identify design patterns in this model itself, and then realize the patterns in code. Thereafter [SumiHui45]  , students analyze the advantages that may have been achieved by the application of the identified patterns.

       这样的经历致使我们去考虑可供选择的教授设计模式的方法。[1]和[5]的作者提倡模式应被用作系统地跟踪良好架构系统的编码实现,并且在编码过程中实现设计准则。在本文中,我们描述一种用来创建软件模型的技术----说明系统行为的“控制图”(也就是说,它们在高层次隐藏了某些细节),但仍然以高精确度被创建。然后我们从这个模型本身里识别出设计模式,并在编码过程中实现这个模式。从那时以后,通过对已识别模式的应用,学生分析其优点的目的可能就已经达到了。

 

Features of our design technique

       Our design technique requires the creation of high quality models of software behavior, documented [SumiHui46]  by UML sequence diagrams. It is applicable to the design of software products from the domain of three-tier [SumiHui47]  architecture systems, whose components map to the Model-View-Controller (MVC) architecture. The first tier (front end) is comprised [SumiHui48]  of view objects, the middle tier (business logic) is comprised of controller objects, and the third tier (back end) is comprised of model objects that interface with the back-end relational database. Figure 1 shows a sequence diagram including these objects, and modeling the behavior of a Withdraw Money use case of a Bank ATM system we demonstrate in class.

 

我们的设计方案的特点

       我们的设计方案要求创建高质量的软件行为模型,由UML序列图组成的文档。那些些软件产品的组件都映射到“模型-视图-控制(MVC)”架构上的三层架构系统,可以应用到软件产品的设计中。第一层(前端)是由视图对象组成,中间层(业务层)是有控制器对象组成,第三层(后台)由连接了后台关系数据库的业务对象组成。图1展示了一个包含这些对象的序列图,并且我们在课程中展示建立了一个银行自动取款机系统退款行为的用例模型。

 

       In figure 1, the User actor refers to all view objects. User requests originate from views, and are processed by controller objects. The Teller object is the main controller, which executes the login process. Once it knows that a withdraw transaction is desired [SumiHui49]  , it delegates [SumiHui50]  further processing to a Use Case Controller [7] ( i.e. , the WithdrawTransaction object). These controllers interface with the Account, AccountHolder and AccountCollection model objects, which encapsulate [SumiHui51]  data from database table rows, and bear the responsibilities of moving data to/from these rows. We teach our students that responsibilities should be distributed to objects that encapsulate the data required to handle them – e.g. ,the Account object assumes the responsibility of checking and decrementing [SumiHui52]  the balance, as it encapsulates the balance value retrieved [SumiHui53]  from the database.

       在图1中,用户(User)涉及到所有的视图对象。用户请求通过视图发起,并且由控制器对象处理。Teller对象是主控制器,执行登录处理。一旦它知道一个退出交易被请求,它就委托一个用例控制器[7](也就是 WithdrawTransaction 对象)做进一步处理。这些控制器连接了AccountAccountHolderAccountCollection 模型对象,这些对象封装了从数据库表行中(读取的)数据,并且承担在这些行中插入或删除数据的职责。我们教导我们的学生职责应该被分派给封装了数据请求的对象去操控----例如,Account对象假定负责检查和扣减余额,当它重新从数据库中读取余额数值时。

 

Figure 1: Sequence Diagram of the Withdraw Money Use Case

1:退款用例序列图

       High precision is achieved in these diagrams by checking them for data-flow and control-flow consistency [SumiHui54]  . We present an overview of these techniques in this paper-further details are available in [8]. Data-flow consistency requires verifying that objects only interface with other objects, and use data, that they know. An object knows other globally known objects, and it knows objects it creates or receives as message parameters and return values. If it wishes to interface with these objects outside the scope in which it first got to know them, it must store them in its attributes (e.g., Teller in Figure 1 stores the AccountHolder object it creates during the processing of the login( id, pwd ) user request, because it needs to use it when processing the later user request withdraw Similarly, the WithdrawTransaction object gets to know the AccountHolder object cust because it receives it as a parameter of the create(..) message sent to it. In the course of processing this message, WithdrawTransaction stores cust in its attributes, because it needs to interface with cust after it has finished processing the create (..) message – i.e., when it is processing the execute() message).

       通过检查这些图中数据流和控制流的一致性,高精度就达到了。在本文中我们呈现的是这些技术的概览—更进一步的细节可以从[8]获得。数据流一致性要求验证对象仅仅通过它们知道的数据和其它对象进行通信。一个对象知道其它全局已知的对象,而且它知道这些对象创建或接受消息参数并返回值。如果它想和这些外部范围内第一次接触的对象通信,它就必须在它的成员属性里存储它们(例如,图1中的Teller存储了在login(id, pwd)用户请求处理过程中创建的AccountHolder(账户处理)对象,因为当处理新的同样的用户退出请求时它需要使用这个对象,WithdrawTransaction(退出交易)对象开始知道AccountHolder客户对象,因为它接受了AccountHolder对象作为create(..)消息的一个参数传给它。在这个消息的处理过程中,WithdrawTransaction在它的成员属性里存储了客户对象,因为当它处理execute()消息时,在它已经完成create(..)消息的处理后,它需要和客户对象通信。)

       Control-flow consistency is based on the principle that the object currently in control must send the next message. If an object receives control by being the recipient [SumiHui55]  of a message, then the next message in the timelines must originate [SumiHui56]  from this object. Return messages hand control back to the object that had sent the corresponding [SumiHui57]  invocation [SumiHui58]  messages. A good way to check this consistency is to have students play the role of objects, and represent control with a token (e.g., a little ball). Only the person who currently has the ball sends the next message. When they send this message, they give the ball to the person who plays the message’s destination [SumiHui59]  . Everyone remembers from whom they last received the ball, and returns it to that person at the appropriate [SumiHui60]  time.

       控制流一致性是基于这样一个原则:当前处于被控制状态的对象必须发送下一条消息。如果一个对象通过成为一个消息的接受者接受控制,那么在时间线上,下一条消息必须由这个对象所发出(引起)。返回消息传递控制回到已经发送了相应的请求消息的对象。一个检查一致性的好方式就是,让学生扮演对象的角色,并用记号表现控制(例如,一个小球)。仅当前拥有小球的人可以发送下一条消息。当他们发送这个消息时,他们把球给扮演消息终点的人。每个人都记住他们上一次从谁那里收到的小球,并在适当的时候把球返还给那个人。

       Behavior models created using this approach must be mapped to high quality code. Such high quality is achieved by ensuring low coupling [SumiHui61]  between communication objects and avoiding code repetition. These are also the key ideas behind ensuring extensibility and maintainability. Low coupling can be achieved by ensuring that objects are coupled to interfaces, and not implementation classes [4]. Identifying the right design pattern helps to achieve this goal. In the following sections, we discuss our technique for identifying some of the GoF patterns in sequence diagrams.

       使用这个方法创建的行为模型必须被映射成高质量的代码。这样的高质量通过在通信对象间确保低耦合和避免代码重复来达成。这些也是确保可扩展性和可维护性背后的关键思想。低耦合可以通过确保对象被耦合到接口,而不实现类[4]来达成。识别出正确的设计模式能帮助达成这一目标。在接下来的章节里,我们讨论从序列图中识别一些GoF模式的技巧。

 

Discovering patterns in behavior models: factory method

We first discuss this pattern because the process of discovering its applicability in our models illustrates the manner in which interfaces that objects must implement are identified. Methods that must be part of the specification of a class C are identified by the set of ‘in-arrows’ that come into all objects of class C in all sequence diagrams in our models. We may discover that a set of methods with the same signatures is part of the specification of different classes. Objects from these classes could then be made to implement a common interface. For example, the create (Teller t, AccountHolder cust) and execute () methods implemented by the WithdrawTransaction object in Figure1 are also implemented by a Deposit-Transaction object, which is part of a different sequence diagram ( for the Deposit Money use case) not shown in this paper. If this is the case, these objects could both implement the Transaction interface – and the create(Teller t, AccountHolder cust) and execute () methods mentioned above are defined by this interface. Any client of these objects, such as the Teller object of Figure 1, can then be coupled to this interface, rather than to the individual classes. Such coupling can be achieved if this client converses with these objects only via the methods defined in the interface – Figure 1 indicates that this is indeed the case with the Teller client. But if the client is required to create instances of these classes, as Teller in Figure 1 is required to do, then this responsibility may result in their becoming coupled to the classes (because code (Java) in the form of ‘new WithdrawTrasaction(…)’ needs to be written). This coupling can be avoided by using the Factory Method pattern. We show possible implementations of this pattern from [4], and demonstrate how the client can be coupled to just the ‘product’ interface and to the ‘creator’ interface for the product.

As an example, a Transaction Factory method for the example shown in Figure 1 can be declared in a TransFactory class as follows:

…Transaction createTransaction(String transType, Teller t, AccountHolder c){

       //…

       if(transType.equals(“Withdraw”)) return new WithdrawTransaction(t,c);

       if(transType.equals(“Deposit”)) return new DepositTransaction(t,c);

       //… }

The code in the withdraw() method of the Teller class of Figure 1 would be as follows:

public void withdraw(){

       //invoke the Factory method; assume we know a ‘ cust ’ object already

       Transaction t=TransFactory.createTransactiion(“Withdraw”,this,cust);

       t.execute(); }

The Teller class is thus coupled only to the TransFactory class and the Transaction interface, and not to the actual classes WithdrawTransaction, DepositTransaction, etc.

 

Discovering patterns in behavior models : strategy

Figure 2. Elaborating a sequence diagram with further details

       The key to discovering the suitability of the Strategy pattern is the presence of self-messages. High-level sequence diagrams use self-messages as placeholders for the execution of algorithms whose details are not of interest at that level. When mapping the model to code, these messages are elaborated using additional delegates as shown in Figure 2. This elaboration process might start form the realization that the same self-message, when sent under different conditions, maps to different algorithms (e.g., objects of a certain class sending a sort() self-message might execute a merge-sort algorithm under certain conditions, whereas under other conditions, they might execute a quick-sort algorithm). These algorithms should then be coded in separate delegate classes implementing the same Strategy object. The use of Strategy objects decouples the implementation of the algorithms from the implementation of its invoker, and uses the preferred approach of using delegation rather than extension.

 

Discovering patters in behavior models: template method

       During the process of mapping our models to Java code, an important issue to consider is whether an interface identified at the design level maps to a Java interface, which has no method bodies, or to a Java abstract class, which allows methods with bodies. It may be possible to resolve this issue by analyzing objects o 1 of type Subclass 1 and o2 of type Subclass2, both of which implement interface I, as shown in Figure 3.

Figure 3. Subclasses responding to method IM1 (…) defined in the superclass/interface

       In diagrams such as those shown in Figure 3, we first ask student to check if , in response to the same incoming message IM1 (…) to pairs of objects like o1 and o2, all outgoing messages from o1 and o2, including self-messages, have the same signatures. Thereafter, they are asked to check if these messages are sent to objects of the same types, and are invoked in the same order. If these conditions are met, the incoming message IM1(..) is a possible candidate for a template method. For example, in both diagrams in Figure 3, in response to IM1(..), outgoing messages OM1(..) and OM2(..) are received by objects of type Type1 and Type2 respectively, and are invoked in the same order. Self-message SM(..) is also invoked between the invocations of OM1(..) and OM2(..) by both objects. Therefore, IM1(..) could be a template method, and students should consider mapping the design interface I to an abstract class containing the body of IM1(..). Self-message will typically be abstract ‘hook’ methods ([4]) declared in this abstract class.

       To illustrate the discovery of the template method pattern in the Bank ATM system, consider the processing of the message execute() by the Withdraw-Transaction object wt in Figure 1. Note that all other Use Case Controller objects of type Transaction (e.g., DepositTransaction, WithdrawTransaction, Transfer-Transaction, etc. –not shown in this paper) also process this message as shown in Figure 1 –namely, by first requesting the customer id from a (known) AccountHolder object and then creating an AccountCollection object using this id. In a more detailed sequence diagram, the response message sent back after creating the AccountCollection object is actually a message that creates and then displays a transaction-specific view to the user. We now see that method execute() can be a template method in the Transaction superclass, and the message to create and display the view is a ‘hook’ method. Thus, code repetition across several subclasses of Transaction can be avoided.

 

Discovering patterns in behavior models: observer

       The applicability of the Observer pattern is indicated by the presence of call backs in the sequence diagram. We first instruct students in detail about the distinction between a return message (dotted line in UML) and a callback message (solid line).A return message simply returns control to the caller, but a callback is often used to apprise the caller of a change in the receiver’s state. Using the examples in Figure 4, we explain that messages OM1() and OM4() are callbacks to the object that sent triggering messages. Control will return to the original sender (e.g. o1) only after the original receiver (i.e. o2) processes the returns from all messages it sent out. The presence of callbacks might increase coupling between classes –e.g., in Figure 4, Class1 and Class3 must know the implementation details of Class2,and Class2 must know the details of both Class1 and Class3. The latter coupling can be avoided by judicious use of the Observer pattern. Callbacks are seen frequently in sequence diagrams in interactions between the user (i.e., a View object) and Controller objects (see Figure 1).

Figure 4. Callbacks in sequence diagrams

Classroom experience

       In four earlier offerings (2011-2014) of our second software engineering course, we taught it by using the “catalog approach”. At the end of the course, we asked them to reflect on the following two issues:

1.    The ease with which design patterns could be identified for application in parts of the code.

2.    The quality of the software created as a result of applying design patterns.

Nineteen student reflections from these offerings indicated that the vast majority of students (79%) found it difficult to identify and apply patterns in their projects. Students wanted more class time to be devoted to presenting additional examples of each pattern taught. Also, in code review sessions with the instructors, student teams had to be repeatedly instructed to revise code. The instructors noted that these revisions mainly consisted of ‘re-modularizing’ several parts of the projects, as students tended to make their code monolithic. A good example of this was found in view classes, where students followed recommended Java Swing coding idioms when attaching anonymous Listener objects to GUI controls – e.g.,

       someButton.addActionListener(new ActionListener(){

              public void actionPerformed(..){

                     //all code to process user action written here

       }});

Students had to be instructed to simplify the code in the ‘actionPerformed()’ method to invoke methods on the controller object associated with the view containing this code, and then use the Observer pattern to enable the controller to call back this view. Such code reviews and revisions were essential for ensuring the creation of maintainable code, but , as indicated by the course evaluations, were not appreciated by students at crunch times of the semester. Moreover, with increasing enrollments, conducting numerous code review sessions with multiple student teams became challenging.

       As a result of these experiences, we realized that it was important to emphasize that the mapping from model to code must be strictly followed. It is also important to emphasize that identifying the right design patterns to use is a part of this mapping. We modified our teaching approach in the last two offerings (2015 and 2016) as described in this paper. Specifically, we taught our students to identify the four patterns: Factory Method, Strategy, Template Method and Observer in sequence diagrams as discussed in this paper. We also taught a number of other GoF patterns, such as Adapter, Bridge, Decorator and Mediator using the “catalog approach”, we sought student reflections on the same two questions mentioned above, and obtained 40 reflections. About 67% of these students stated that they were able to easily identify certain design patterns in sequence diagrams. These primarily included the four patterns we describe in this paper. But many of our students were also able to identity the use of the other GoF patterns we presented, as we discuss later in this section.

       We note that these students were more enthusiastic in their responses to the second question above. Over 90% of the reflections indicated that students saw reducing coupling and avoiding repeated code as the most important goals. Students stated that in seeking to achieve these goals, they employed techniques that “turned out” to be design patterns. As a result of this mindset, we observed that our students noted similarities between design patterns. These similarities are observed by the GoF authors ([4]), but they were not discussed in class. For example, 67% of our students reflected that the Observer and Mediator patterns had similar behaviors, as seen in the sequence diagrams. The only difference was that observer mandated the names of the methods in the involved classes, but the Mediator did not. In the context of the Strategy pattern, let us start by stating that almost all students found the elaboration approach as shown in Figure 2 useful. To quote one student:“If the code looks like it is getting too complex, then, knowing it will probably change later, we decided to break out the code into its own class, and ensure that the caller knows the caller (delegate) object through an interface it implements. We then saw that we could break the code out further into still less complex delegates. So we essentially get a chain of small delegates to deal with complexity, and get the extensibility and maintainability wanted in our project”. In these resulting delegate chains, students saw similarities between various GoF patterns. For example, about 10% of the students saw similarities between the Strategy and Bridge patterns (as did the authors of [3], whose pattern identification tools did not easily distinguish between these two patterns). About 20% of our students saw similarities between the Strategy and Adapter patterns:“If the delegate implements the same interface, we have the Decorator pattern; but if different, it is the Adapter pattern.” To quote one of the 25% of students who saw similarities between Strategy and Decorator patterns:“You call it a Decorator if you add the second delegate you think of between the caller and the first (Strategy) delegate you already put in. As long as your job gets done by the delegates, and they are loosely coupled, I am not too focused on what the technique is called”.

       Thus, we see that our approach enabled students to focus on enhancing code quality. In fact, given the emphasis on similarities between patterns that a significant number of our students mentioned in their reflection documents (although they were not asked to identify such similarities), we strongly feel that students are focused on achieving low coupling between communicating objects, and avoiding code replication, by “any means possible” –i.e., they try to discover a way of accomplishing this whether they use a design pattern in the “traditional sense” (i.e., exactly as it is defined in the GoF book ([4]) or not. This result is possibly a challenge to instructors who wish their students to be aware of the exact structural and behavioral details of design patterns, so that the names of design patterns may be used as a vocabulary for effective communication between designers. We intend to consider this issue in our future work, as described in the section below.

       Finally, let us mention that over the last two offerings of our second software engineering course, code reviews of 10 student teams (with 4-5 members per team) showed that revisions requested are no longer so extensive, and ‘re-modularization’ revision requests have practically disappeared.

 

Conclusions and plans for future work

       Teaching design patterns by presenting a catalog of patterns, or by using ‘killer’ examples/case studies, usually consists of teaching the characteristics of the patterns themselves, and then illustrating how using them improved code quality. Our approach was to start with high-level behavior models that have an appropriate set of communicating objects. We then focus on mapping these models to code with the primary aim that these objects be loosely coupled and code replication be avoided. Ideas provided by design patterns are simply the tools to achieve these goals. Our experience indicates that students primarily focus on code quality, and their project code is much improved from earlier offerings. In this process, it is possible that students may lose focus on the name and exact details of a particular pattern. This may be a drawback in situations where pattern names are used as a vocabulary to communicate design ideas. Therefore, we are currently exploring whether it is possible to use ideas from design patterns at the modeling stage itself. An important fact to note is that among the details associated with a pattern is the intent of the designer/programmer – e.g., in [4], the GoF authors state that the Decorator pattern applies when the “skin” around a code segment changes, whereas the Strategy pattern applies when the “guts” within the segment itself change. Such intent is hard to convey in sequence diagrams. We intend to explore whether such intents can be kept in mind when creating the model itself, or when elaborating it as shown in Figure 2. We conjecture that such an approach may result in the objects used in the sequence diagrams being named appropriately –i.e., given names that indicate the pattern that will apply. We also intend to explore models from other product domains such as games to see if they provide opportunities to identify certain GoF patterns we have not been able to identify in the three-tier architecture models we have considered so far.

 

References

[1]   Allison, C., Harrison, N., Teaching Design Patterns: A Matter of Principle, Journal of Computing Sciences in Colleges 23 (1), 206-211, 2007.

[2]   Denzler, C., Gruntz, D., Design Patterns:Between Programming and Software Design, Proceedings of the 30th international Conference on Software Engineering (ICSE), Leipzig, Germany, 801-804, 2008.

[3]   Dong, J., Zhao, Y., Experiments on Design Pattern Discovery, Proceedings of the Third International Workshop on Predictor Models in Software Engineering (PROMISE 07) 2007, Vancouver, BC.

[4]   Gamma, E., Helm, R., Johnson, R., Vlissides, J., Design Patterns: Elements of Reusable Object-Oriented Software, New York, NY: Addison-Wesley, 1995.

[5]   Gast, H., Patterns and Traceability in Teaching Software Architecture, Proceedings of the 6th International Symposium on Principles and Practice of Programming in Java (PPPJ), Modena, Italy, 23-31, 2008.

[6]   Gestwicki, P., Shin, F., Teaching Design Patterns Through Commputer Game Development, ACM Journal on Educational Resources in Computing 8 (1), 2:1-2:21, 2008.

[7]   Larman, C., Applying UML and Patterns (3rd Ed.), Upper Saddle River, NJ: Prentice-Hall, 2005.

[8]   Mitra, S., Using UML Modeling to Facilitate Three-Tier Architecture Projects in Software Engineering Courses, ACM Transaction on Computing Education 14(3), 17:1 – 17:31, 2014.

[9]   Weiss, S., Teaching Design Patterns By Stealth, Proceedings of the 36th SIGCSE Technical Symposium on Computer Science Education (SIGCSE), St. Louis, MO, USA, 492-494, 2005.

 

 


  [SumiHui1] adj. 可延长的;可扩张的

  [SumiHui2] adj. 可维持的;可主张的;可维修的

  [SumiHui3] n. 概念,观念;思想(concept复数形式)

  [SumiHui4] 深入地;全面地

  [SumiHui5] n. 地图;示意图;染色体图

vt. 映射;计划;绘制地图;

  [SumiHui6] vt. 评定;估价;对征税

  [SumiHui7] v. 评估

  [SumiHui8] 我们通过在学期项目中评估在采用我们的技术后代码的开发质量和早期项目的对比来评估我们的方法

  [SumiHui9] n. 反光;反响,回声;回旋曲

  [SumiHui10] reflection on 反思,反射对

  [SumiHui11] adj. 连续的;继承的;依次的;接替的

  [SumiHui12] n. 学期(semester的复数)

  [SumiHui13] adv. 显著地;相当数量地

  [SumiHui14] (使)持续,延续;扩展到

  [SumiHui15] n. 自定义;客制化;自定义级别

v. 定制;按特别订货生产

adj. 定制的;用户化的

  [SumiHui16] n. 修改,修正;改变

  [SumiHui17] n. 增加;放大

  [SumiHui18] n. 环境;上下文;来龙去脉

  [SumiHui19] adv. 精确地,准确地

  [SumiHui20] n. 目的;利益;理由;日本米酒

  [SumiHui21] v.(使)增加;产生,获得,积累

  [SumiHui22] v. 促使;刺激;给与动机

  [SumiHui23] n. 有插画的报章杂志

adj. 有插图的

v. 阐明;举例说明;给加插图

 

  [SumiHui24] adv. 非此即彼;二者择一地;作为一种选择

  [SumiHui25] 使用案例

  [SumiHui26] 招人喜爱的例子;

Ps.类似用法的短语还有:Killer app(计算机行业中的一个行话),意为“招人喜爱的应用程序,杀手级应用程序(极具创意、功能强大、非常有用),先进一流的应用软件”

  [SumiHui27] adv. 也就是;即是;换句话说

  [SumiHui28] n. 租金收入,租金;租赁

adj. 租赁的;收取租金的

  [SumiHui29] 童子军?

  [SumiHui30] n. 移动;变化;手段;轮班

  [SumiHui31] 假定;臆断;想当然

  [SumiHui32] 后来;稍后;过些时候

  [SumiHui33] 计算机术语中,意为“恢复正常操作”

  [SumiHui34] adj. 不适当的;不相称的

  [SumiHui35] vt. 重做;修订

  [SumiHui36] adv. 显著地;相当数量地

  [SumiHui37] 高压时期,紧缩时期

  [SumiHui38] n. 二中择一;供替代的选择

adj. 供选择的;选择性的;交替的

  [SumiHui39] n. 提倡者;支持者;律师

vt. 提倡,主张,拥护

  [SumiHui40] n. [车辆] 车辆;工具;交通工具;运载工具;传播媒介;媒介物

  [SumiHui41] adv. 有系统地;有组织地

  [SumiHui42] n. 痕迹,踪迹;微量;[] 迹线;缰绳

vt. 追踪,查探;描绘;回溯

vi. 追溯;沿路走

abbr.   [SumiHui43] 也就是,亦即

  [SumiHui44] n. 精度,[] 精密度;精确

adj. 精密的,精确的

  [SumiHui45] adv. 其后;从那时以后

  [SumiHui46] adj. 备有证明文件的

  [SumiHui47] n. 层,排;行,列;等级

  [SumiHui48] v. 包含(comprise的过去分词);由组成

  [SumiHui49] adj. 渴望的;想得到的

v. 渴望,要求(desire的过去分词形式)

  [SumiHui50] n. 代表(delegate的复数)

v. 选举为代表;委托职责

  [SumiHui51] 封装;压缩;概述;装入胶囊

  [SumiHui52] n.减量,缩减;降低;衰减率

  [SumiHui53] v. 恢复;重新取回;补偿;挽救(retrieved的过去分词)

  [SumiHui54] n. [] 一致性;稠度;相容性

  [SumiHui55] n. 容器,接受者;容纳者

  [SumiHui56] vt. 引起;创作

vi. 发源;发生;起航

  [SumiHui57] adj. 相当的,相应的;一致的;通信的

  [SumiHui58] n. 祈祷,符咒

  [SumiHui59] n. 目的地,终点

  [SumiHui60] adj. 适当的;恰当的;合适的

vt. 占用,拨出

  [SumiHui61] n. [] 耦合;结合,联结

目录
相关文章
|
6月前
|
设计模式 关系型数据库
【设计模式——学习笔记】设计模式简介+七大设计原则介绍(下)
【设计模式——学习笔记】设计模式简介+七大设计原则介绍
21 0
|
1月前
|
设计模式 算法 API
适配器模式:C++设计模式中的瑞士军刀
适配器模式:C++设计模式中的瑞士军刀
48 0
|
5月前
|
设计模式
设计模式系列教程(03) - 设计模式分类及六大原则
设计模式系列教程(03) - 设计模式分类及六大原则
27 0
|
6月前
|
设计模式 Java 程序员
【设计模式——学习笔记】设计模式简介+七大设计原则介绍(上)
【设计模式——学习笔记】设计模式简介+七大设计原则介绍
29 2
|
11月前
|
设计模式 XML 数据可视化
【架构设计模式】MITRE 设计模式
【架构设计模式】MITRE 设计模式
|
11月前
|
设计模式 SQL 缓存
【设计模式】【第九章】【设计模式小结】
单一职责原则:一个类只负责一个功能领域中的相应职责 开闭原则:一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展
|
设计模式 自然语言处理 Java
重新学习设计模式一:什么是设计模式
一直以来,设计模式是一个令人头疼的课题,记得之前在A公司做智能客服项目时,刚开始只是一个小项目,不管什么设计模式,系统架构,全程直接上手敲业务代码,两三天时间就把所有的代码敲完上线使用,结果谁也没想到突然项目大起来了,十几个业务部门的业务一拥而上,开始招人,上手业务,结果。。。大家都是苦力干嘛,拼命加班,拼命填坑,十几个人的代码乱七八糟,大量重复业务,重复代码,单简单的一样表单业务查询就有三四不同的版本,新来的员工也在抱怨没学到任何技术,倒学会怎么跟业务吵架,那日子实在是不忍直视。。。
71 0
|
设计模式 API C#
unity 项目开发——浅谈设计模式的六大原则(二)
unity 项目开发——浅谈设计模式的六大原则(二)
158 0
|
设计模式 JSON 安全
unity 项目开发——浅谈设计模式的六大原则(一)
unity 项目开发——浅谈设计模式的六大原则(一)
116 0
|
设计模式 存储 JavaScript
一起学习设计模式:备忘录模式——软件的“后悔药”
备忘录是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态, 并将其保存下来。 备忘录模式就像是软件中的“后悔药”,可以在软件中实现后悔机制的设计模式。
一起学习设计模式:备忘录模式——软件的“后悔药”