简介: 软件行为模型中的设计模式,翻译自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



Sandeep Mitra 和 T. M. Rao



(电话):585 395-2234



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.






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.



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.





       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


       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.



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.



[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. [] 耦合;结合,联结

设计模式 算法 安全
【设计模式】RBAC 模型详解
随着软件系统的复杂性和规模的不断增长,权限管理成为了一个至关重要的问题。在大型多人协作的系统中,如何有效地管理不同用户的访问权限,确保系统的安全性和稳定性,是每一个开发者都需要面对的挑战。为了解决这一问题,业界提出了一种被广泛应用的权限管理模型——基于角色的访问控制(Role-Based Access Control,简称RBAC)。希望通过本篇博客的学习,您能够深入了解RBAC模型的核心思想和实现原理,掌握如何在实际项目中应用RBAC模型来提高系统的安全性和可维护性。
341 1
设计模式 前端开发 安全
设计模式 安全 Java
74 1
设计模式 领域建模 数据库
设计模式 存储 前端开发
76 0
设计模式 存储 前端开发
115 0
设计模式 安全 Java
java 设计模式实战,原始模型模式之写作业,克隆以后就是新的
通过给出一个原型对象指明所要创建的对象的类型,然后通过复制这个原型对象来获取的更多的同类型的对象。 这让我不由自主的想起克隆技术,还记得克隆羊吗?
java 设计模式实战,原始模型模式之写作业,克隆以后就是新的
设计模式 Kubernetes Java
2300 0
Java 设计模式 安全
  谈到Akka就必须介绍Actor并发模型,而谈到Actor就必须看一篇叫做《A Universal Modular Actor Formalism for Artificial Intelligence 》的论文,它最早发表于1973年,提出了一种并发计算的理论模型,Actor就源于该模型。
8192 0