Software architecture involves the integration of software development methodologies and models, which distinguishes it from particular analysis and design methodologies. The structure of complex software solutions departs from the description of the problem, adding to the complexity of software development. Software architecture is a body of methods and techniques that helps us to manage the complexities of software development.
Software architecture presents a view of a software system as components and connectors. Components encapsulate some coherent set of functionality. Connectors realize the runtime interaction between components. The system design achieves certain qualities based on its composition from components and connectors. Software architecture design is not entirely different from existing software design methodologies. Rather it complements them with additional views of a system that have not been traditionally handled by methodologies like object-oriented design.
What is Software Architecture?
The software architecture of a program or computing system is the structure or structures of the system, which comprise software elements, the externally visible properties of those elements (“Externally visible” properties are those assumptions other elements can make of an element, such as it provided services, performance characteristics, fault handling, shared resource usage, and so on.), and the relationships among them.
An architecture is foremost an abstraction of a system that suppresses details of elements that do not affect how they use, used by, relate to, or interact with other elements. Generally, elements interact with each other by means of interfaces that partition details about an element into public and private parts. Architecture is concerned with the public side of this division (usually referred to as the interface of an element). Architecture consists of several structures Module, Component-and- connector and Allocation.
Architecture Patterns, Reference Models, and Reference Architectures
An architectural patter as a description of element and relation types together with a set of constraints on how they maybe used. A pattern can be thought of as a set of constraints on an architecture-on the element types and their patterns of interactions-and these constraints define a set or family of architectures and satisfy them. The term architecture style has also been widely used to describe the same concept.
A reference model is a division of functionality together with data flow between the pieces. A references mode is a standard decomposition of a known problem into parts that cooperatively solve the problem. Arising from experience, reference models are a characteristic of mature domains.
Reference architecture is a reference model mapped onto software elements (that cooperatively implement the functionality defined in the reference model) and the data flows between them.
Architectural Structures and Views
Modern systems are more than complex enough to make it difficult to grasp them all at once. Instead we restrict our attention at any moment to one of the software system’s structures. To communicate meaningfully about an architecture we must make clear which structure we are discussing at the moment- which view we are taking of the architecture. A view is a representation of a coherent set of architectural elements, as written by and read by system stakeholders. It consists of a representation of a set of elements and the relations among them. A structure is the set of elements itself, as they exist in the software or hardware.
Architectural structures can by large be divided into three groups, depending on the broad nature of the elements they show.
· Module Structures: Here the elements are modules which are units of implementation. Modules represent a code-base way of considering the system. They are assigned areas of functional responsibility. There is less emphasis on how the resulting software manifests it self at runtime. Module structures allow us to answer questions such as what is the primary functional responsibility assigned to each module? What other software elements is a module allowed to use? What other software does it actually use? What modules are related to other modules by generalization or specialization relationships?
· Component-and-connector structures: Here the elements are runtime principle units of computation (components) and the communication vehicles among them (connectors). These structures help answer questions such as what are the major executing components and how do they interact? How does data progress through the system? What parts of the system can run n parallel? How can the system’s structure changes as it executes?
· Allocation Structures: These show the relationship between the software elements and the elements in one or more external environments in which the software is created and executed. They answer questions such as what processor does each software element executes on? In what files each element stored during development, testing and system Building? What is the assignment of software element o development teams?
Figure 1: Software Architecture Structures
These three broad types of structures are further classified to:
· Decomposition: The units are modules related to each other by the “is a sub module of” relation, showing how larger modules are decomposed into smaller ones recursively until they are small enough to be easily understood. The decomposition structure provides a large part of the system’s modifiability, by ensuring that likely changes fall within the purview of at most a few small modules.
· Uses: The units are related by the uses relation. One unit uses another if the correctness of the first requires the presence of the second. The uses structure is used to engineer systems that can be easily extended to add functionality or from which useful functional subsets can be easily extracted.
· Layered: When the uses relations in this structure are carefully controlled in a particular way, a system of layers emerges, in which a layer is a coherent set of related functionality. Layers are often designed as abstractions that hide implementation specifics below from the layers above, engendering portability.
· Class: The module units in this structure are called classes. The relation is “inherits-from” or “is-an-instance-of”. This view supports reasoning about collections of similar behaviour or capability and parameterized differences which are captured by sub classing. The class structure allows us to reason about re-use and the incremental addition of functionality.
· Process: The units here are process or threads that are connected with each other by communication, synchronization, and/or exclusion operations. The relation is attachment, showing how the components are hooked together. The process structure is important in helping to engineer a system’s exaction performance and availability.
· Concurrency: This structure allows the architect to determine opportunities for parallelism and the locations where resource contention may occur. The units are logical threads. A logical thread is a sequence of computation that can be allocated to a separate physical thread.
· Shared data: this structure show components and connectors that create, store, and access persistent data. It shows how data is produced and consumed by runtime software elements and it can be used to ensure good performance and data integrity.
· Client-Server: The components are the clients and servers and the connectors are protocols and messages they share to carry out the system’s work. This is useful for separation of concerns, physical distribution and load balancing.
· Deployment: this shows how software is assigned to hardware-processing and communication elements. This view allows to reason about performance, data integrity, availability, and security.
· Implementation: This shows how software elements are mapped to the file structure in the system’s development, integration or configuration control environments. This is critical for the management of development activities, and builds processes.
· Work Assignment: This view assigns responsibility for implementing and integrating modules to the appropriate development teams. Having a work assignment structure as part of the architecture makes it clear that the decision about who does the work has architectural as well as management implications.
Quality is often in the eye of the beholder. What this means for the architect is that customers may dislike a design because their concept of quality differs from the architect’s. Quality attribute scenarios are the means by which quality moves from the eye of the beholder to a more objective basis. We explore different type of quality that may be appropriate for architecture. Six important attributes (Availability, Modifiability, Performance, Security, Testability, and usability) I will review how to generate scenarios for them and how to characterize quality requirements. Then I will list the tools in the architect’s kit that are used to achieve the quality attributes.
Business considerations determine qualities that must be accommodated in a system’s architecture. These qualities are over and above that of functionality, which is the basic statement of the system’s capabilities, services, and behaviour. Although functionality is and other qualities are closely related, functionality often takes not only the front seat in the development scheme but the only seat. System are frequently redesigned not because they are functionally deficient but because they are difficult to maintain, port, scale, too slow, or have been compromised by network hackers.
Functionality is the ability of a system to do the work for which it was intended. A task requires that many or most of the system’s elements work in a coordinated manner to complete the job. Functionality maybe achieved through the use of any of a number of possible architectures. Instead it is decomposed into module to make it understandable and to support a verity of other purposes.
Achieving quality attributes must be considered throughout design, implementation, and deployment. No quality attribute is entirely dependent on design, nor is it entirely dependent on implementation or deployment. Satisfactory results are a matter of getting the big picture (architecture) as well as the details (implementation) correct.
Understanding Quality Attributes
· Availability: is concerned with system failure and its associated consequences. A system failure occurs when the system no longer delivers a service consistent with its specification. Such a failure is observable by the system’s users. Areas of concern for availability are: how system failure is detected, how frequent it may occur, what happens when a failure occurs, how long a system is allowed to be out of operation, when failures may occur safely, how failure can be prevented, and what kinds of notifications are required when a failure occurs.
· Modifiability: is about the cost of change. What can be changed (the artifact)? , When is the change made? And who makes the change?
· Performance: is about timing, Events (interrupts, messages, request from users) occur, and the system must respond to them.
· Security: is a measure of the system’s ability to resist unauthorized usage while still providing it services to legitimate users.
· Testability: refers to the ease with which software can be made to demonstrate its faults testing. At least 40% of the cost of developing well engineered systems is taken up by testing.
· Usability: is concerned with how easy it is for the user to accomplish a desired task and the kind of user support the system provides. It can be broken into:
o Learning system features
o Using a system efficiently
o Minimizing the impact of errors
o Adapting the system to user needs
o Increasing confidence and satisfaction
Achieving Quality Attributes
A system design consists of a collection of decisions. Some of these decisions help control the quality attribute responses; others ensure achievement of system functionality. We will discuss quality attribute decisions known as Tactics. Each Tactic is a design option for the architect.
A failure occurs when the system no longer delivers a service that is consistent with its specification; this failure is observable by the system’s users. A fault has the potential to cause a failure. Recovery or repair is an important aspect of availability.
Ping/Echo: one component issues a ping and expects to receive back an echo within a predefined time, from components under scrutiny.
Heartbeat: in this case one component emits a heart beat message periodically and another component listens for it. If the heart beat fails the originating component is assumed to have failed and a fault correction component is notified.
Exceptions: An exception is raised when one of the fault classes is recognized. The exception handler notifies a correction component.
Voting: Process running on redundant processors each take equivalent input and compute a simple output value that is sent to a voter. If the voter detects a deviant behavior from a single processor it fails it.
Active Redundancy: All redundant components respond to events in parallel. Consequently, they are all in the same state. The response from only one component is used, and the rest are discarded. When a fault occurs, the downtime is usually milliseconds since the backup is current and the only time to recover is the switching time.
Passive Redundancy: one component responds to events and informs the other components of state updates they must take. When fault occurs, the system must first ensure that the backup state is sufficiently fresh before resuming services. This approach is also used in control systems, often when the inputs come over communication channels or from sensors and have to be switched from the primary to the backup on failure.
Spare: A standby spare computing platform is configured to replace many different failed components. It must be rebooted to the appropriate software configuration and have its state initialized when a failure occurs. Making a checkpoint of the system state to a persistent device periodically and logging all state changes to a persistent device allows the spare to be set to the appropriate state. The downtime for this tactic is usually minutes.
Shadow Operation: A previously failed component may be run in shadow mode for a short time to make sure it mimics the behavior of the working component before restoring it to service.
State resynchronization: The passive and active redundancy tactics require the component being restored to have its state upgraded before its return to service. The updating approach will depend on the downtime hat can be sustained, the size of the update, and the number of messages required for the update. A single message containing the state is preferable, if possible. Incremental state upgrades, with periods of service between increments, lead to complicated software.
Checkpoint/rollback: A checkpoint is a recording of a consistent state created either periodically or in response to specific events. Sometimes a system fails in an unusual manner, with a detectably inconsistent state. In this case the system should be restored using a previous checkpoint of a consistent state and a log of the transactions that occurred since the snapshot was taken.
Removal from service: remove a component from service to undergo some activities to prevent anticipated failures.
Transactions: A transaction is the bundling or several sequential steps such that the entire bundle can be undone at once.
Process Monitor: Once a fault in a process has been detected a monitoring process can delete the nonperforming process and create a new instance of it.
The goal is controlling the time and cost to implement, test, and deploy changes
Localize Modifications: reduce the number of modules that are affected by a change. The goal is to assign responsibilities to modules during design such that anticipated changes will be limited in scope.
Maintain Semantic Coherence: this refers to the relationships among responsibilities in a module. The goal is to ensure that all of these responsibilities work together without excessive reliance on other modules.
Anticipate expected changes: considering the set of envisioned changes provides a way to evaluate a particular assignment of responsibilities.
Generalize the module: Making a module more general allows it to compute a broader range of functions based on input.
Limit possible options: Modifications, especially within a product line may be far ranging and hence affect many modules. Restricting the possible options will reduce the effect of these modifications.
Prevent Ripple Effects: limit modifications to the localized modules. A ripple effect from a modification is the necessity of making changes to modules not directly affected by it.
Hide information: this is the decomposition of the responsibilities for an entity into smaller pieces and choosing which information to make private and which to make public.
Maintain Existing interface: If module B depends on the name and signature of interface of module A, maintaining this interface and its syntax allows module B to remain unchanged.
Restrict communication paths: restrict the modules with which a given module shares data. That is, reduce the number of modules that consume data produced by the given module and the number of modules that produce data consumed by it.
Use and intermediary: if module B has any type dependency on module A other than semantic, it is possible to insert an intermediary between module A and module B that manages activities associated with the dependency.
Defer Binding Time: When a modification is made by the developer, there is usually a testing and distribution process that determines the time lag between the making of the change and the availability of that change to the end user. Binding at runtime means that the system has been prepared for that binding and all of the testing and distribution steps have been completed. Deferring binding time also supports allowing the end user or system administrator to make setting or provide input that affects behavior.
Runtime registration: Publish/subscribe for example.
Configuration files: are intended to set parameters at startup.
Polymorphism: allows late binding of method calls
Component replacement: allows load time binding.
Adherence to defined protocols: allows runtime binding of independent processes.
The goal is to generate a response to an event arriving at the system within some time constraint.
· Reduce Demand: Event streams are the source of resource demand. Two characteristics of demand are the time between events in a resource stream and how much of a resource is consumed by each request.
o Reduce required resources:
§ Increase Computational efficiency: Improving the algorithms used in critical areas will decrease latency
§ Reduce computational overhead: the use of intermediaries increases the resources consumed in processing an event stream, and so removing them improves latency.
o Reduce the number of events processed:
§ Manage event rate: reduce the sampling frequency at which environmental variables are monitored, demand can be reduces
§ Control frequency of sampling: queued requests can be sampled at a lower frequency, possibly resulting in the loss of requests.
o Control the use of resources:
§ Bound execution times: place a limit on how much execution time is used to respond to an event.
§ Bound queue sizes: this controls the maximum number of queued arrivals and consequently the resources used to process the arrivals.
· Resource Management: Even though the demand for resources may not be controllable, he management of these resources affects response times.
o Introduce concurrency: if requests can be processed in parallel, the blocked time can be reduced.
o Maintain multiple copies of either data or computations: the purpose of replicas is to reduce the contention that would occur if all computations took place on a central server.
o Increase Available resources: Faster processors, additional processors, additional memory, and faster networks all have the potential of reducing latency.
· Resource arbitration: whenever there is a contention for a resource. The resource must be scheduled. The architect’s goal is to understand the characteristics of each resource’s use and choose the scheduling strategy that is compatible with it.
· Resisting Attack:
o Authenticate users: Authentication is ensuring that a user or remote computer is actually who it purports to be.
o Authorize users: Authorization is ensuring an authenticated user has the rights to access and modify either data or services.
o Maintain data confidentiality: Data should be protected from unauthorized access.
o Maintain integrity: data should be delivered as intended.
o Limit exposure: attacks typically depend on exploiting a single weakness to attack all data and services on a host. The architect can design the allocation of services to hosts so that limited services are available on each host.
o Limit access: Firewalls restrict access based on message source or destination port.
· Detecting Attacks: The detection of an attack is usually through an intrusion detection system: Such systems work by comparing network traffic patterns to a database.
· Recovering from Attacks:
o Restoring State: these overlap with availability tactics.
o Identifying an attacker: maintain an audit trail. It also support non repudiation (provides evidence that a particular request was made).
The goal is to allow for easier testing when an increment of software development is completed. Executing the test procedures requires some software to provide input to the software being tested and to capture the output. This is called a test harness.
o Record/playback: refers to both capturing information crossing an interface and using it as input into the test harness.
o Separate interface from implementation. Separating the interface from the implementation allows substitution of implementations for various testing purposes.
o Specialize access routes/interfaces: having specialized testing interfaces allows the capturing or specification of variable values for a component through a test harness as well as independently from its normal execution.
· Internal monitoring: a component can implement tactics based on internal stat to support the testing process.
o Built in monitors: The component can maintain state, performance load, capacity, security or other information accessible through an interface.
Usability is concerned with how easy it is for the user to accomplish a desired task and the kind of support the system provides to the user.
Designing the Architecture
Grady Booch once said “All successful object-oriented share two common traits: the existence of a strong architectural vision and the application of a well –managed iterative and incremental development cycle”.
The Attribute Driven Design (ADD) method is a method for designing architecture to satisfy both quality requirements and functional requirements. ADD takes as input a set of quality attribute scenarios and employs knowledge about the relation between quality attribute achievement and architecture in order to design the architecture. ADD is an approach to defining a software architecture that bases the decomposition process on the quality attributes the software has to fulfill. It is a recursive decomposition process where at each stage, tactics and architectural patterns are chosen to satisfy a set of quality scenarios and the functionality is allocated to instantiate the module types provided by the pattern.
Choose the module to decompose: the module to start with is usually the whole system. All required inputs for this module should be available.
Refine the module according to these steps:
Choose the architecture drivers from the set of concrete quality scenarios and functional requirements. This step determines what is important for this decomposition.
Choose an architectural pattern that satisfies the architectural drivers. Create (or select) the pattern based on the tactics that can be used to achieve the drivers. Identify child modules required to implement the tactics.
Instantiate modules and allocate functionality from the use cases and represent using multiple views.
Define interfaces of the child modules. The decomposition provides modules and constraints on the types of module interactions. Document this information in the interface document for each module.
Verify and refine use cases and quality scenarios and make them constraints for the child modules. This step verifies that nothing important was forgotten and prepares the child modules for further decomposition or implementation.
Repeat the steps above for every module that needs further decomposition
Once the first few levels of the architecture’s module decomposition structure are fairly stable, those modules can be allocated to development teams. The result is the work assignment view.
Documenting the Architecture
The architecture serves as the blueprint for both the system and the project developing it. It defines the work assignments that must be carried out by design and implementation teams and it is the primary carrier of system qualities such as performance, modifiability, and security-none of which can be achieved without a unifying architectural vision. Architecture is an artifact for early analysis to make sure that the design approach will yield an acceptable system. Remember that we defined software architecture for a system as “the structure or structures of the system, which comprise elements, the externally visible properties of those elements and the relationships among them. A view is a representation of a coherent set of architectural elements, as written by and read by system stakeholders. Documenting architecture is a matter of documenting the relevant views and then adding documentation that applies to more than one view. This breaks the problem of architecture documentation into more tractable parts:
· Choosing the relevant views: A view simple represents a set of systems elements and the relationships among them. So whatever you deem useful to a segment of the stakeholder community constitute a valid view.
o Produce a candidate view list: Begin by building a stakeholder/view table.
o Combine views: The candidate view list usually has a large number of views. Look for views that are good candidates to be combined-that is, a view that gives information from two or more views at once.
o Prioritize: this depends on the details specific to your project, but remember that you don’t have to complete one view before starting another.
· Documenting a view:
o Overview (primary presentation): shows the elements and the relationships among the m that populate the view.
o Element Catalog: details at least those elements and relations depicted in the overview. Producing the overview is often what architects concentrate on, but without backup information that explains the picture, it is of little value.
o Context diagram: shows how the system depicted in the view relates to its environment in the vocabulary of the view.
o Variability guide: shows how to exercise any variation points that are a part of the architecture shown in this view.
o Architecture background: explains why the design reflected in the view came to be. The goal of this section is to explain to someone why the design is as it is and a convincing argument that it is sound.
o Glossary of terms used in the views with a brief description of each.
· Documenting information that applies to more than one view: Cross view documentation consists of just three major aspects :
o How the documentation is laid out and organized so that a stakeholder of the architecture can find the information efficiently and reliably.
o What the architectures is: a short overview to ground any reader as to the purpose of the system; the way the views are related to each other; a list of elements and where they appear.
o Why the architecture is the way it is: the context for the system, external constraints that have been imposed to shape the architecture.
An interface is a boundary across which 2 independent entities meet and interact or communicate with each other. A template for documenting interfaces:
1. Interface identity
2. Resources provided (IDL, CORBA, WSDL, … etc)
3. Data Type definitions
4. Exception definitions
5. Variability provided by the interface
6. quality attribute characteristics of the interface
7. Element requirements
8. Rational and design issues
9. Usage guide.