Progettazione dettagliata delle Componenti
Cosa significa progettare in dettaglio una componente Progettare un’architettura, usando uno stile architetturale (usando, il più possibile, passaggi o incrementi sistematici, dal modello analitico) Completare l’architettura, usando alcuni pattern architetturali, focalizzandosi sugli attributi di qualità di interesse Analizzare l’architettura, relativamente alla valutazione previsionale della qualità del software (ed ai costi) Progettare in dettaglio le singole componenti dell’architettura, usando pattern di progettazione e, in generale, i principi di progettazione Progettare in dettaglio le singole componenti dell’architettura, usando pattern di progettazione e, in generale, i principi di progettazione (Ri-)Progettazione delle componenti (refactoring) Valutazione previsionale della qualità Descrizione dettagliata delle componenti iterativo
Tipologie di Componente Componenti convenzionali (funzioni, procedure, programmi…) Componenti object-oriented (classi, insiemi di classi, oggetti)
Specifica di una Componente La specifica di una componente è una definizione di cosa necessita e di cosa produce/garantisce (senza dire esattamento come la componente lavora) Tale definizione può essere scritta in una notazione (informale, formale o semiformale); tale definizione dovrebbe essere legata in qualche modo ai requisiti (oppure ad altre componenti) Ad esempio, un modulo che corrisponde a varie funzioni (in un DFD) potrebbe avere una specifica in termini di linguaggio comune ovvero di pre e post condizioni Una componente object-oriented può essere specificata attraverso “classi” ed anche attraverso l’introduzione di diagrammi di sequenza, ove sia classi che diagrammi di sequenza sono legati al modello analitico (oppure ad altre componenti)
(Ri-)Progettazione delle Componenti La ri-progettazione lavora sulle componenti ed in particolare sulla loro specifica Nel caso della progettazione strutturata, la progettazione delle componenti procede applicando di fatto i design principles classici di astrazione, raffinamento, information hiding, indipendenza funzionale, modularità Nel caso di componenti orientate agli oggetti il modo più efficace è l’uso di design pattern In entrambe i casi, se la qualità previsionale risultante non è sufficiente, è ragionevole, applicare il refactoring (ristrutturazione) per migliorare il risultato mantenendo l’”equivalenza”
Esempi di Progettazione root Get… Prenotare&Pagare Put… raffinamento Valida Opzioni di Costo Calcola Costo Design pattern Observer (applicato internamento alla componente Movimento) Subject Observer Piano Ascensore Partire Fermare
Valutazione previsionale della qualità delle componenti: il caso della indipendenza funzionale tra le componenti
Functional Independence: Two Views of a Component
Functional Independence COHESION - the degree to which a module performs one and only one functionality. COUPLING - the degree to which a module is "connected" to other modules in the software. Low Coupling and High Cohesion For each Module is the Design Principle enabling better maintaneability, evolvibiliy, reusability (and not only) Partially, functional independence is guaranteed by a well defined requirement specification, but may be destroyed by bad components Elaborated From Pressman
Degrees of Cohesiveness High coincidental logical temporal procedural sequential communicational functional Degree of cohesion Low
Degrees of coupling Low data stamp control common content High Degree of coupling High
Coincidental cohesion The module allows to perform a set of functions which relate to each other very loosely, if at all: The module contains a random collection of parts. Several parts have been put in the module out of pure coincidence without any thought or design.
Logical cohesion All elements of the module perform similar operations Examples: unique error handling, data input, data output, etc. a set of print functions to generate an output report, arranged into a single module; visualising distinct messages with similar layout
Temporal cohesion The module contains functions that must be executed in the same time span. Example: A unique module responsible for initialization, start-up, shut-down of some process, etc.
Procedural cohesion The parts of the module are involved in sequences of steps are carried out in a certain order for producing results Example: Get Tariffe, Rete
Communicational cohesion All parts of a module reference or update the same data structure Example: Get Tariffe Get Treno-Tariffe Get Regole
Valida Opzioni di Costo Sequential cohesion A module is composed of different parts of a specific sequence, output from one element of the sequence is input to the next Example: Prenotare&Pagare Valida Opzioni di Costo Calcola Costo
Functional cohesion Different parts of a module cooperate to achieve a single functionality When a module displays functional cohesion, we can describe its functionality using a single sentence
Data coupling Two modules are data coupled, if they communicate via a parameter corresponding to: an elementary data item (e.g an integer, a float, a character,…) a composite data item, which contents is fully used The data item should not be used for control purpose.
Stamp coupling Two modules are stamp coupled, if they communicate via a composite data item (i.e. there is a dependency of the structure of data) where some parts of the structure are not used Examples of composite data items: record in PASCAL structure in C class in Java
Control coupling Data from one module is used to direct order of instruction execution in another Example: a flag set in one module and tested in another module root Prenotare? Get… Prenotare&Pagare Put…
Common coupling Two modules are common coupled if they share some global data. Example: Directly referring to the same database or variable Get Tariffe Get Rete
Content coupling Content coupling exists between two modules if they share code in a general sense (code accessing the same internal variables, same data, but also the code needs to be maintained the same)
Evaluating Quality by using Function Indipendence Metrics: one example Quality attributes Maintainability; Evolvabilty; Reusability; Comprehensibility; Low Coupling High Cohesion Metrics Degrees of cohesion, coupling Other Metrics (better) Limited Fan-out and higher Fan-in for each module Modules are loosely coupled and highly cohesive Fan-in, Fan-out (not sure)
Evaluating Quality by using Function Indipendence Metrics: one example Clearly Fan-in and Fan-out metrics are only very approximate ways to understand coupling and cohesion of modules; other metrics are required Example is “online train ticket case study” root Get Viaggio, ViaggioPrenotato, Opzioni di Costo, Opzioni di Prenotazione, Rete, Tariffe, Prenotazioni, Dati CC, Biglietti Prenotare&Pagare Put Costo, Viaggio, Posti, Riepilogo, Prenotazioni, Biglietti Cohesion: Procedural Coupling: Common (with Put), Control (with Prenotare&Pagare) Cohesion : Sequential Coupling: Control (with root) Cohesion: Procedural Coupling: Common (with Get), Control (with Prenotare&Pagare)
Altre “metriche” sulla specifica di una componente sequential cohesion
Coupling in OO Conventional view: OO view: Level of coupling The degree to which a component is connected to other components and to the external world OO view: a qualitative degree to which classes are connected to one another Level of coupling Content Common Control Stamp Data Routine call Type use Inclusion or import External A little bit different from the previous list of coupling levels Sometimes referred to as design pattern (low coupling) From Pressman
Cohesion in OO Conventional view: OO view: Levels of cohesion the “single-mindedness” of a module OO view: cohesion implies that a component or class encapsulates only attributes and operations that are closely related to one another and to the class or component itself Levels of cohesion Functional Layer Communicational Sequential Procedural Temporal Utility A little bit different from the previous list of cohesion levels Sometimes referred to as design pattern (high cohesion) From Pressman
Refactoring: Generalised View Fowler [FOW99] defines refactoring in the following manner: "Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code [design] yet improves its internal structure.” Similar to design patterns but design patterns are for building the (non existing) components while refactoring (patterns) is (are) for changing the existing components When software is refactored, the existing design model is examined by following empirical ways for redundancy unused design elements inefficient or unnecessary algorithms poorly constructed or inappropriate data structures or any other design failure that can be corrected to yield a better design. Elaborated From Pressman
Refactoring in Structured Design Generally speaking, it is a way for increasing cohesion per module and decreasing the overall coupling with the objective of minimizing the potential duplication of code in each module separating work modules from management modules (in a structure chart) providing more generally useful modules simplifying the future code management modules work modules
Refactoring (Online Train Tickets) root Get Viaggio, Opzioni di Costo, Opzioni di Prenotazione, Rete, Tariffe, Prenotazioni, Dati CC Prenotare&Pagare Put Costo, Viaggio, Posti, Riepilogo, Prenotazioni, Biglietti Refinement Prenotare Pagare Cohesion : Functional Coupling: Data (with Get and Put) Abstraction Cohesion: Procedural Coupling: Control (with GetPut), Control (with Prenotare&Pagare) Cohesion: Procedural Coupling: Control (with GetPut), Control (with Prenotare&Pagare) Get All Tables Put All Tables Cohesion : CommunicationCoupling:
Refactoring per componenti OO Il refactoring nel caso di componenti OO opera soprattutto a livello di codice (cioè una volta che le componenti sono state completamente descritte ovvero codificate in qualche linguaggio di programmazione) Un esempio è presentato nel trasparente successivo E’ comunque possibile fare del refactoring durante il progetto (cioè operando su rappresentazioni quali il diagramma delle classi, gli statechart etc., ed è forse anche meglio!
Refactoring Class Diagram Example A limited definition of each class is needed Prenotazione Viaggio Treno Prenotazione Treno Viaggio Partially, the need of refactoring the design model may be decreased by a well defined requirement specification
Descrizione dettagliata delle componenti
Describing the internal structure of conventional components The objective is to define the alghoritms and the data types (by reusing th existing alghoritms and data types) Flow chart, PDL and Decision Tables (see Pressman) can be employed From Pressman
Flow Chart We are all familiar with the flow chart representations: Flow chart is a convenient technique to represent the flow of control in a system. A=B if(c == 100) P=20 else p= 80 while(p>20) print(student mark) A=B yes no P=20 P=80 dummy yes no Print From Pressman
Flow Chart versus Structure Chart A structure chart differs from a flow chart in three principal ways: It is difficult to identify modules of a software from its flow chart representation. Data interchange among the modules is not represented in a flow chart. Sequential ordering of tasks/steps inherent in a flow chart is suppressed in a structure chart. From Pressman
Decision Table From Pressman
Program Design Language (PDL) if-then-else if condition x then process a; else process b; endif PDL easy to combine with source code machine readable, no need for graphics input graphics can be generated from PDL enables declaration of data as well as procedure easier to maintain From Pressman
Describing the internal structure of classes Operations (and how they can be used) must be defined: detailed statecharts for the class are the support for this purpose; however, in simple case, operations can be synthesized from pre and post conditions Class invariants can be used as well Data types for class attributes must be defined Associations should be implemented Inheritance and polymorphism can be used as well (and Framework)
Inheritance Options An existing class hierarchy can be searched to determine if a class higher in the hierarchy (a superclass) contains most of the required attributes and operations. The new class inherits from the superclass and additions may then be added, as required. The class hierarchy can be restructured so that the required attributes and operations can be inherited by the new class. Characteristics of an existing class can be overridden and different versions of attributes or operations are implemented for the new class. From Pressman
Polymorphism From Pressman Conventional approach … case of graphtype: if graphtype = linegraph then DrawLineGraph (data); if graphtype = piechart then DrawPieChart (data); if graphtype = histogram then DrawHisto (data); if graphtype = kiviat then DrawKiviat (data); end case; All of the graphs become subclasses of a general class called graph. Using a concept called overloading [TAY90], each subclass defines an operation called draw. An object can send a draw message to any one of the objects instantiated from any one of the subclasses. The object receiving the message will invoke its own draw operation to create the appropriate graph. graphtype draw From Pressman
Object Oriented Frameworks A object-oriented framework is not an architectural pattern, but rather a skeleton with a collection of “plug points” (also called hooks and slots) that enable it to be adapted to a specific problem domain It is like the earlier concept of library of modules Gamma et al. note that: Design patterns are more abstract than frameworks. Design patterns are smaller architectural elements than frameworks Design patterns are less specialised than frameworks From Pressman
Conclusioni Increment and tranformation guidelines/rules Requirement engineering Quality attributes Design engineering Architectural views (stakeholders) Design principles Detailed comp. design Architecture design Component design Architectural patterns Architectural styles Design patterns FI,R,A,M,H
Conclusioni Le strategie proposte hanno la caratteristica della sistematicità e, quindi, realizzano la tracciabilità dai requisiti al modello di progetto Un processo di sviluppo del software prevede a questo punto la costruzione e il test del software costruito Modulo (Modello di progetto) Classe (Modello analitico) Classe (Modello di progetto) Funzione (Modello analitico) reqX (doc. requisiti) reqX (doc. requisiti)