• 沒有找到結果。

Modern large-scale software systems bear complex internal structures to match the complexity of the problems they solve. To help software developers derive such complex structures from initial problem formulation, numerous software engineering methods and techniques have been proposed and developed over the years. Different approaches address the development process from different perspectives and/or focus on different parts. General paradigms like object and component technologies or programming techniques such as design patterns are just some of the most widely recognized examples.

However, the prominence of these various software engineering techniques also creates an additional dimension of complexity, namely, the burden for software developers to master these techniques. For example, the object-oriented paradigm provides extremely powerful abstraction mechanisms so that there is virtually no limit about how implementation can be expressed to solve a given problem. It becomes the developer’s job to exploit what object technology can offer, and reflect them in actual system design and implementation.

Not surprisingly, new approaches have been initiated just to help software developers in handling these powerful tools. For example, design patterns [1] are one such attempt to document recurrent object-oriented designs that are proven to be successful, so that not only novice developers can gain insight into effective object-oriented design quickly compared to otherwise try-and-error efforts, but also the intent of a given design become easier to convey among experience developers. Another popular example that helps developers in dealing with complex software structures is aspect-oriented programming (AOP) [2], which has been proposed as a new programming paradigm with language support to enable cleaner decomposition of functionality or other aspects of software systems. The same principle of separation of concerns is also the theme underlying another recent trend in component-based development (CBD) [3][4], where systems are developed by assembling well-defined, often prefabricated components to reduce development time and increase quality.

However, with these successive waves of technology innovations coming, many software developers find themselves overwhelmed, evidenced by the tutorials and books published to answer the demands. The sheer volume of design patterns has made it difficult to answer the fundamental questions such as which, when, how, and why a design pattern is preferred for a given situation, no matter how well these patterns are documented. On the

other hand, although AOP reveals issues that commonly arise with object technology when software evolves, for people willing to experiment with the idea but are more familiar with

“traditional” object-oriented approaches, what is the better approach to reconcile both techniques is by no means obvious and takes time and efforts to answer.

General paradigms like CBD can also be understood in a similar way. First of all, the ambiguity of terms like component has made it difficult to determine which ingredients are essential to CBD. Even if we agree that CBD emphasizes more on principles – systematic application of black-box reuse and design by contract – and can coexist smoothly with object technology, critical issues such as: how to incorporate OO and CBD concepts, how to harness heterogeneous components within a particular project, how to design systems so that they are more robust against changes from component suppliers and requirements, or how to secure current efforts by making components and design reusable for future projects, etc., are all nontrivial questions to answer for people willing to exploit the benefits of CBD.

The structural complexity also incur substantial burden for developers in the maintenance or evolution phase after the initial system is implemented, as it is widely recognized that the evolution of a software system often takes a degeneration path. As different pieces of the overall software design often relate with each other in an convoluted way that is the result of intensive analysis and tradeoffs, it is understandable that adding new artifacts or modifying existing ones while conforming to the original design principles and constraints will be non-trivial, especially if substantial efforts are needed to uncover the considerations and tradeoffs embedded within the system in various, sometime implicit forms.

Adding these reverse engineering efforts with the efforts needed to understand the paradigms and technologies used to produce the system in the first place, and the learning curve will turn only worse.

Despite the advent of various technologies that claim their usefulness and benefits for improvement, experienced developers often can stand firmly against these successive waves of innovations if they are armed with solid software engineering disciplines. Fundamental principles such as information hiding and divide-and-conquer practice are results of years of research and experiences. They help developers avoid misunderstanding and ensure proper adoption of new concepts and techniques. In fact, many modern software technologies can be appreciated much easier with these principles.

Unfortunately, there are still substantial gap between general software engineering principles and how to make use of them in practice. Like design patterns, the principles provide even more general rules and guidance about the objectives and strategies of software construction. Reflecting these general principles in actual design, however, still need experience, which can be quite painful. This is somewhat inevitable, however, due to the substantial gap one has to fill between the high-level principles and extremely powerful, but nevertheless low-level software construction mechanisms such as OOP. Furthermore, principles of different flavors also emerge and overlap with each other, and seeing through the intents and driving forces behind them may not be straightforward. Take information hiding as an example. It only gives a general principle (or hint) about encapsulation and separating interface from implementation, along with the resulting dramatic benefits.

However, for problems more complex than a simple client/server pair, the number of possible ways to define interfaces increases explosively and to find a reasonable set of interfaces that divide the overall system requires proper applications of other principles, plus trials and errors to some degree.

The objective of this thesis is to propose a simple conceptual framework in which complex software designs can be represented and analyzed in a systematic manner. The motivation is that, by simplifying design representation and by making design evaluation explicit, design decisions and review can be done more clearly and objectively. To achieve the goal, we propose a generic component model, accompanied with a straightforward graphical notation that is capable of capturing software designs at various abstraction levels ranging from high-level architectures to low-level code fragments. The component model consists of basic concepts such as domain, context, polymorphism, collaboration, and management that together provide developers with a stylized way of decomposing large software designs.

While concepts presented throughout this thesis such as components, patterns, reuse, etc.

are not new, our attempt to reconcile various technologies into a simple yet pragmatic conceptual framework is unique. Although our component model in some sense place some constraints about software designs compared to using more expressive object-oriented models, we believe the gains in understandability and evolution can be substantial. We believe the framework provides software developers an immediately useful tool which not only can help them make good design decisions, but also can assist them sieving through related literatures. In addition, the simplicity of the framework can serve well as a foundation

for the development of corresponding CASE tools, such as assisting design tracking and refactoring systematically. In summary, our framework complements nicely with current approaches.

For the purpose of this thesis, we refer “design” in a general sense to any software artifact that reveals the structures of (part of) a software system, regardless the abstraction level. In other words, a design may be a high-level architecture, an object-oriented analysis or design model, a design pattern, or the internal organization within a Java class.

The rest of the thesis is organized as follows: in chapter 2 we describe the generic component model, followed by several component- and reuse-oriented design guidelines. In chapter 3 we describe the design annotation and evaluation framework based on the ideas presented in the thesis. In section 4 we describe additional metrics and refactoring support on top of the framework described in chapter 3. In section 5 we discuss some related work and other related issues, and conclude the paper in section 6.

相關文件