The term Ajax has come to represent a broad group of web technologies that can be used to implement a web application that communicates with a server in the background, without interfering with the current state of the page. In the article that coined the term Ajax, Jesse James Garrett explained that the following technologies are incorporated:
- HTML (or XHTML) and CSS for presentation
- The Document Object Model (DOM) for dynamic display of and interaction with data
- XML for the interchange of data, and XSLT for its manipulation
- The XMLHttpRequest object for asynchronous communication
This presentation shall provide you an overview of AJAX and understanding of all the necessary building blocks of an AJAX application.
Architecture, patterns and programming skills
Architecture and Design
Programming and code
ORM and Database
Process and methodology
People & Process for beginners
- Ship it!
is a good introductory book for doing Agile in practice. It's not as
technical as pragmatic programmer, more project/soft oriented.
People & Process advanced
People & Process classics
Off-topic, but related books
How to write text
Here you will find pointers to manuals, tutorials and references that will come in handy when you feel like coding in Ruby.
An interactive tutorial that lets you try out Ruby right in your browser. This 15-minute tutorial is aimed at beginners who want to get a feeling of the language.
This is a small Ruby tutorial that should take no more than 20 minutes to complete. It makes the assumption that you already have Ruby installed. (If you don’t have Ruby on your computer download and install it before you get started.)
The Koans walk you along the path to enlightenment in order to learn Ruby. The goal is to learn the Ruby language, syntax, structure, and some common functions and libraries. We also teach you culture.
The little coder’s starter kit. A fun and easy way to learn about programming (through Ruby) using the Shoes GUI Toolkit.
An unconventional but interesting book that will teach you Ruby through stories, wit, and comics. Originally created by why the lucky stiff, this guide remains a classic for Ruby learners.
A wonderful little tutorial by Chris Pine for programming newbies. If you don’t know how to program, start here.
Coming to Ruby from another language? Whether it’s C, C++, Java, Perl, PHP, or Python, this article has you covered!
A thorough collection of Ruby study notes for those who are new to the language and in search of a solid introduction to Ruby’s concepts and constructs.
Ruby Essentials is a free on-line book designed to provide a concise and easy to follow guide to learning Ruby.
A site that aims to provide well-organized, rich content tutorials for both Ruby and Rails.
The seminal work on Ruby in English, this first edition of the Pragmatic Programmers’ book is available for free online.
Translated from the original Japanese version written by Yukihiro Matsumoto (the creator of Ruby), this version, by Goto Kentaro and Mark Slagell is nice overview of many aspects of the Ruby language.
A free online manual with beginner and intermediate content plus a thorough language reference.
Pulled straight from the source code using RDoc, this reference work documents all of the core classes and modules (like String, Array, Symbol, etc…).
Also pulled from the source code using RDoc, this reference work documents the standard library
Documentation for Ruby’s underlying C code. Great if you want to write C extensions or contribute to Ruby’s development.
The one-stop web site for reference documentation about Ruby gems and GitHub-hosted Ruby projects.
Rails and Ruby documentation with smart searching.
Ruby, Rails, Gem and Plugin Documentation.
Some key definitions related to Architecture, design principles, design patterns and overall object oriented analysis and design for quick reference.
The extent to which software is divided into components, called modules, which have high internal cohesion, low coupling between each other, and simple interfaces.
A measure of the extent to which related aspects of a system are kept together in the same module, and unrelated aspects are kept out.
A measure of the extent to which interdependencies exist between software modules.
Creating a module to contain some algorithm or data structure, thus hiding its details behind the module's interface. Allows changes to code to be more easily made since one can be confident that 'outsiders' are not relying on too many details
Hiding details so as to reduce complexity.
The ability for software to be run in a variety of different hardware or software environments with no or minimal changes.
"Subclasses" are more specialized versions of a class, which inherit attributes and behaviors from their parent classes, and can introduce their own.
Simplifying complex reality by modelling classes appropriate to the problem, and working at the most appropriate level of inheritance for a given aspect of the problem.
Polymorphism allows the programmer to treat derived class members just like their parent class's members. More precisely, Polymorphism in object-oriented programming is the ability of objects belonging to different data types to respond to calls of methods of the same name, each one according to an appropriate type-specific behavior. One method, or an operator such as +, -, or *, can be abstractly applied in many different situations.
Decoupling allows for the separation of object interactions from classes and inheritance into distinct layers of abstraction. A common use of decoupling is to polymorphically decouple the encapsulation, which is the practice of using reusable code to prevent discrete code modules from interacting with each other. However, in practice decoupling often involves trade-offs with regard to which patterns of change to favor. The science of measuring these trade-offs in respect to actual change in an objective way is still in its infancy.
High-Level Design (HLD)
A HLD provides an overview of a solution, platform, system, product, service, or process. Such an overview is important in a multi-project development to make sure that each supporting component design will be compatible with its neighbouring designs and fits in the big picture. HLD should briefly describe all platforms, systems, products, services and processes that it depends upon and include any important changes that need to be made to them. A high-level design document will usually include a high-level architecture diagram depicting the components, interfaces and networks that need to be further specified or developed. The document may also depict or otherwise refer to work flows and/or data flows between component systems. In addition, there should be brief consideration of all significant commercial, legal, environmental, security, safety and technical risks, issues and assumptions. The idea is to mention every work area briefly, clearly delegating the ownership of more detailed design activity(LLD-Low-Level Design) whilst also encouraging effective collaboration between the various project teams. Today, most high-level designs require contributions from a number of experts, representing many distinct professional disciplines. Finally, every type of end-user should be identified in the high-level design and each contributing design should give due consideration to customer experience.
Low Level Design (LLD)
It is like detailing the HLD. It defines the actual logic for each and every component of the system. Class diagrams with all the methods and relation between classes comes under LLD. Programs specs are covered under LLD. LLD describes each and every module in an elaborate manner so that the programmer can directly code the program based on this.There will be at least 1 document for each module and there may be more for a module.The LLD will contain: - detailed functional logic of the module in pseudo code - database tables with all elements including their type and size - all interface details with complete API references(both requests and responses) - all dependency issues -error message listings - complete input and outputs for a module. LLD is supposed to be used as program specifications for the developer.
Unified Modeling Language (UML)
UML is a standardized general-purpose modeling language in the field of software engineering. The standard is managed, and was created by, the Object Management Group. UML includes a set of graphic notation techniques to create visual models of software-intensive systems.
Layering decomposition is some ordering of principles, typically abstraction. The layers may be totally or partially ordered, such that a given layer x uses the services of layer y, and x in turn provides higher-level services to any layer that uses it. Layering can be by layers or tiers. Layering is usually a top-level decomposition and is followed by one of the other rules.
The Unified Modeling Language (UML) is used to specify, visualize, modify, construct and document the artifacts of an object-oriented software intensive system under development. UML offers a standard way to visualize a system's architectural blueprints, including elements such as:
- business processes
- (logical) components
- programming language statements
- database schemas, and
- reusable software components.
UML combines techniques from data modeling (entity relationship diagrams), business modeling (work flows), object modeling, and component modeling. It can be used with all processes, throughout the software development life cycle, and across different implementation technologies. UML is a single, common and widely usable modeling language that aims to be a standard modeling language which can model concurrent and distributed systems
There are four parts to the UML 2.x specification:
- The Superstructure that defines the notation and semantics for diagrams and their model elements;
- the Infrastructure that defines the core metamodel on which the Superstructure is based;
- the Object Constraint Language (OCL) for defining rules for model elements;
- and the UML Diagram Interchange that defines how UML 2 diagram layouts are exchanged. For example you can auto generate a sequence diagram from Collaboration diagrams and vice-versa
UML 2.2 has 14 types of diagrams divided into two categories. Seven diagram types represent structural information, and the other seven represent general types of behavior, including four that represent different aspects of interactions. These diagrams can be categorized hierarchically as shown in the following class diagram:
Some points worth noting about UML diagrams are
- UML does not restrict UML element types to a certain diagram type
- Every UML element may appear on almost all types of diagrams
- UML profiles may define additional diagram types or extend existing diagrams with additional notations.
- In keeping with the tradition of engineering drawings, a comment or note explaining usage, constraint, or intent is allowed in a UML diagram.
Lets now briefly walk through all diagram types in UML
Structure diagrams emphasize what things must be in the system being modeled:
- Class diagram: describes the structure of a system by showing the system's classes, their attributes, and the relationships among the classes.
- Component diagram: depicts how a software system is split up into components and shows the dependencies among these components.
- Composite structure diagram: describes the internal structure of a class and the collaborations that this structure makes possible.
- Deployment diagram: serves to model the hardware used in system implementations, and the execution environments and artifacts deployed on the hardware.
- Object diagram: shows a complete or partial view of the structure of a modeled system at a specific time.
- Package diagram: depicts how a system is split up into logical groupings by showing the dependencies among these groupings.
- Profile diagram: operates at the metamodel level to show stereotypes as classes with the <<stereotype>> stereotype, and profiles as packages with the <<profile>> stereotype. The extension relation (solid line with closed, filled arrowhead) indicates what metamodel element a given stereotype is extending.
Since structure diagrams represent the structure they are used extensively in documenting the architecture of software systems.
Behavior diagrams emphasize what must happen in the system being modelled:
- Activity diagram: represents the business and operational step-by-step workflows of components in a system. An activity diagram shows the overall flow of control.
- State machine diagram: standardized notation to describe many systems, from computer programs to business processes.
- Use case diagram: shows the functionality provided by a system in terms of actors, their goals represented as use cases, and any dependencies among those use cases.
Since behavior diagrams illustrate the behaviour of a system, they are used extensively to describe the functionality of software systems.
Interaction diagrams, a subset of behaviour diagrams, emphasize the flow of control and data among the things in the system being modeled:
- Communication diagram: shows the interactions between objects or parts in terms of sequenced messages. They represent a combination of information taken from Class, Sequence, and Use Case Diagrams describing both the static structure and dynamic behavior of a system.
- Interaction overview diagram: are a type of activity diagram in which the nodes represent interaction diagrams.
- Sequence diagram: shows how objects communicate with each other in terms of a sequence of messages. Also indicates the lifespans of objects relative to those messages.
- Timing diagrams: are a specific type of interaction diagram, where the focus is on timing constraints.
The Protocol State Machine is a sub-variant of the State Machine. It may be used to model network communication protocols.
In software engineering, a design pattern is a general reusable solution to a commonly occurring problem in software design. A design pattern is not a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations. Object-oriented design patterns typically show relationships and interactions between classes or objects, without specifying the final application classes or objects that are involved.Design Patterns are broadly classified into three categories.
These patterns have to do with class instantiation. They can be further divided into class-creation patterns and object-creational patterns. While class-creation patterns use inheritance effectively in the instantiation process, object-creation patterns use delegation to get the job done.
- Builder constructs complex objects by separating construction and representation.
- Factory Method creates objects without specifying the exact class to create.
- Prototype creates objects by cloning an existing object.
- Singleton restricts object creation for a class to only one instance.
These concern class and object composition. They use inheritance to compose interfaces and define ways to compose objects to obtain new functionality.
- Adapter allows classes with incompatible interfaces to work together by wrapping its own interface around that of an already existing class.
- Bridge decouples an abstraction from its implementation so that the two can vary independently.
- Composite composes zero-or-more similar objects so that they can be manipulated as one object.
- Decorator dynamically adds/overrides behaviour in an existing method of an object.
- Facade provides a simplified interface to a large body of code.
- Flyweight reduces the cost of creating and manipulating a large number of similar objects.
- Proxy provides a placeholder for another object to control access, reduce cost, and reduce complexity.
Most of these design patterns are specifically concerned with communication between objects.
- Command creates objects which encapsulate actions and parameters.
- Iterator accesses the elements of an object sequentially without exposing its underlying representation.
- Mediator allows loose coupling between classes by being the only class that has detailed knowledge of their methods.
- Memento provides the ability to restore an object to its previous state (undo).
- Observer is a publish/subscribe pattern which allows a number of observer objects to see an event.
- State allows an object to alter its behavior when its internal state changes.
- Strategy allows one of a family of algorithms to be selected on-the-fly at runtime.
- Template method defines the skeleton of an algorithm as an abstract class, allowing its subclasses to provide concrete behavior.
- Visitor separates an algorithm from an object structure by moving the hierarchy of methods into one object.
While designing an application of any size or complexity, the most important thing that an architect should never loose track of are these design principles which are being discussed in the following section. Design principles are the backbone and inspiration behind all design patterns that exist today. If an architect understands these design patterns thoroughly and religiously practice them in his designs then he will mostly get it right no matter whether he knows all design patterns by heart or not. No no, I am not advocating that you don't need to learn design patterns, all I am trying to convey here is that if one understands these design principles it will be a lot easier for one to understand the details and philosophy of design patterns. Knowledge of these design principles in-fact complements one's understanding of design patterns. Following are the core design principles:
A module should be open for extension but closed for modification. Of all the principles of object oriented design, this is the most important. It originated from the work of Bertrand Meyer2. It means simply this: We should write our modules so that they can be extended, without requiring them to be modified. In other words, we want to be able to change what the modules do, without changing the source code of the modules.
Subclasses should be substitutable for their base classes. Derived classes should be substitutable for their base classes. That is, a user of a base class should continue to function properly if a derivative of that base class is passed to it.
Depend upon Abstractions. Do not depend upon concretions. If the the Open Closed Principle states the goal of OO architecture, the DIP states the primary mechanism. Dependency Inversion is the strategy of depending upon interfaces or abstract functions and classes, rather than upon concrete functions and classes. This principle is the enabling force behind component design, COM, CORBA, EJB, etc.
Many client specific interfaces are better than one general purpose interface. The essence of the principle is quite simple. If you have a class that has several clients, rather than loading the class with all the methods that the clients need, create specific interfaces for each client and multiply inherit them into the class.
The granule of reuse is the granule of release. A reusable element, be it a component, a class, or a cluster of classes, cannot be reused unless it is managed by a release system of some kind. Users will be unwilling to use the element if they are forced to upgrade every time the author changes it. Thus. even though the author has released a new version of his reusable element, he must be willing to support and maintain older versions while his customers go about the slow business of getting ready to upgrade. Thus, clients will refuse to reuse an element unless the author promises to keep track of version numbers, and maintain old versions for a while. Therefore, one criterion for grouping classes into packages is reuse. Since packages are the unit of release, they are also the unit of reuse. Therefore architects would do well to group reusable classes together into packages.
Classes that change together, belong together. A large development project is subdivided into a large network of interelated packages. The work to manage, test, and release those packages is non-trivial. The more packages that change in any given release, the greater the work to rebuild, test, and deploy the release. Therefore we would like to minimze the number of packages that are changed in any given release cycle of the product. To achieve this, we group together classes that we think will change together. This requires a certain amount of precience since we must anticipate the kinds of changes that are likely. Still, when we group classes that change together into the same packages, then the package impact from release to release will be minimized.
Classes that aren’t reused together should not be grouped together. A dependency upon a package is a dependency upon everything within the package. When a package changes, and its release number is bumped, all clients of that package must verify that they work with the new package -- even if nothing they used within the package actually changed. We frequently experience this when our OS vendor releases a new operating system. We have to upgrade sooner or later, because the vendor will not support the old version forever. So even though nothing of interest to us changed in the new release, we must go through the effort of upgrading and revalidating. The same can happen with packages if classes that are not used together are grouped together. Changes to a class that I don’t care about will still force a new release of the package, and still cause me to go through the effort of upgrading and revalidating.
The dependencies betwen packages must not form cycles. Since packages are the granule of release, they also tend to focus manpower. Engineers will typically work inside a single package rather than working on dozens. This tendency is amplified by the package cohesion principles, since they tend to group together those classes that are related. Thus, engineers will find that their changes are directed into just a few package. Once those changes are made, they can release those packages to the rest of the project. Before they can do this release, however, they must test that the package works. To do that, they must compile and build it with all the packages that it depends upon. Hopefully this number is small.
Depend in the direction of stability.
Information hiding is the principle of segregation of design decisions in a computer program that are most likely to change, thus protecting other parts of the program from extensive modification if the design decision is changed. The protection involves providing a stable interface which protects the remainder of the program from the implementation (the details that are most likely to change).
Coupling is a measure of how strongly one element is connected to, has knowledge of, or relies on other elements. An element with low (or weak) coupling is not dependent on too many other elements. A class, for example, with high (or strong) coupling relies on many other classes. Such classes may be undesirable.
High Cohesion attempts to keep objects appropriately focused, manageable and understandable. High cohesion is generally used in support of Low Coupling. High cohesion means that the responsibilities of a given element are strongly related and highly focused. Breaking programs into classes and subsystems is an example of activities that increase the cohesive properties of a system.
Core J2EE patterns are broadly classified in the following three categories based on the layering of the multi tiered systems. A specific patterns applies to a specific layer of the system under development
- Intercepting Filter intercepts incoming requests and outgoing responses and applies a filter. These filters may be added and removed in a declarative manner, allowing them to be applied unobtrusively in a variety of combinations. After this preprocessing and/or post-processing is complete, the final filter in the group vectors control to the original target object. For an incoming request, this is often a Front Controller, but may be a View.
- Front Controller is a container to hold the common processing logic that occurs within the presentation tier and that may otherwise be erroneously placed in a View. A controller handles requests and manages content retrieval, security, view management, and navigation, delegating to a Dispatcher component to dispatch to a View.
- Application Controller centralizes control, retrieval, and invocation of view and command processing. While a Front Controller acts as a centralized access point and controller for incoming requests, the Application Controller is responsible for identifying and invoking commands, and for identifying and dispatching to views.
- Context Object encapsulates state in a protocol-independent way to be shared throughout your application. Using Context Object makes testing easier, facilitating a more generic test environment with reduced dependence upon a specific container.
- View Helper encourages the separation of formatting-related code from other business logic. It suggests using Helper components to encapsulate logic relating to initiating content retrieval, validation, and adapting and formatting the model. The View component is then left to encapsulate the presentation formatting. Helper components typically delegate to the business services via a Business Delegate or an Application Service, while a View may be composed of multiple subcomponents to create its template.
- Composite View suggests composing a View from numerous atomic pieces. Multiple smaller views, both static and dynamic, are pieced together to create a single template. The Service to Worker and Dispatcher View patterns represent a common combination of other patterns from the catalog. The two patterns share a common structure, consisting of a controller working with a Dispatcher, Views, and Helpers. Service to Worker and Dispatcher View have similar participant roles, but differ in the division of labor among those roles. Unlike Service to Worker, Dispatcher View defers business processing until view processing has been performed.
- Service to worker performs core request handling and invoke business logic before control is passed to the view. It centralizes control and request handling to retrieve a presentation model before turning control over to the view. The view generates a dynamic response based on the presentation model.
- Dispatcher View combines a controller and dispatcher with views and helpers to handle client requests and prepare a dynamic presentation as the response. Controllers do not delegate content retrieval to helpers, because these activities are deferred to the time of view processing. A dispatcher is responsible for view management and navigation and can be encapsulated either within a controller, a view, or a separate component.
- Business Delegate reduces coupling between remote tiers and provides an entry point for accessing remote services in the business tier. A Business Delegate might also cache data as necessary to improve performance. A Business Delegate encapsulates a Session Façade and maintains a one-to-one relationship with that Session Façade. An Application Service uses a Business Delegate to invoke a Session Façade.
- Service Locator encapsulates the implementation mechanisms for looking up business service components. A Business Delegate uses a Service Locator to connect to a Session Façade. Other clients that need to locate and connect to Session Façade, other business-tier services, and web services can use a Service Locator.
- Session Façade provides coarse-grained services to the clients by hiding the complexities of the business service interactions. A Session Façade might invoke several Application Service implementations or Business Objects. A Session Façade can also encapsulate a Value List Handler.
- Application Service centralizes and aggregates behavior to provide a uniform service layer to the business tier services. An Application Service might interact with other services or Business Objects. An Application Service can invoke other Application Services and thus create a layer of services in your application.
- Business Object implements your conceptual domain model using an object model. Business Objects separate business data and logic into a separate layer in your application. Business Objects typically represent persistent objects and can be transparently persisted using Domain Store.
- Composite Entity implements a Business Object using local entity beans and POJOs. When implemented with bean-managed persistence, a Composite Entity uses Data Access Objects to facilitate persistence.
- The Transfer Object pattern provides the best techniques and strategies to exchange data across tiers (that is, across system boundaries) to reduce the network overhead by minimizing the number of calls to get data from another tier.
- The Transfer Object Assembler constructs a composite Transfer Object from various sources. These sources could be EJB components, Data Access Objects, or other arbitrary Java objects. This pattern is most useful when the client needs to obtain data for the application model or part of the model.
- The Value List Handler uses the GoF iterator pattern to provide query execution and processing services. The Value List Handler caches the results of the query execution and return subsets of the result to the clients as requested. By using this pattern, it is possible to avoid overheads associated with finding large numbers of entity beans. The Value List Handler uses a Data Access Object to execute a query and fetch the results from a persistent store.
- Data Access Object enables loose coupling between the business and resource tiers. Data Access Object encapsulates all the data access logic to create, retrieve, delete, and update data from a persistent store. Data Access Object uses Transfer Object to send and receive data.
- Service Activator enables asynchronous processing in your enterprise applications using JMS. A Service Activator can invoke Application Service, Session Façade or Business Objects. You can also use several Service Activators to provide parallel asynchronous processing for long running tasks.
- Domain Store provides a powerful mechanism to implement transparent persistence for your object model. It combines and links several other patterns including Data Access Objects.
- Web Service Broker exposes and brokers one or more services in your application to external clients as a web service using XML and standard web protocols. A Web Service Broker can interact with Application Service and Session Façade. A Web Service Broker uses one or more Service Activators to perform asynchronous processing of a request.
What Is an AntiPattern?
AntiPatterns, like their design pattern counterparts, define an industry vocabulary for the common defective processes and implementations within organizations. A higher-level vocabulary simplifies communication between software practitioners and enables concise description of higher-level concepts.
An AntiPattern is a literary form that describes a commonly occurring solution to a problem that generates decidedly negative consequences. The AntiPattern may be the result of a manager or developer not knowing any better, not having sufficient knowledge or experience in solving a particular type of problem, or having applied a perfectly good pattern in the wrong context.
AntiPatterns provide real-world experience in recognizing recurring problems in the software industry and provide a detailed remedy for the most common predicaments. AntiPatterns highlight the most common problems that face the software industry and provide the tools to enable you to recognize these problems and to determine their underlying causes.
Furthermore, AntiPatterns present a detailed plan for reversing these underlying causes and implementing productive solutions. AntiPatterns effectively describe the measures that can be taken at several levels to improve the developing of applications, the designing of software systems, and the effective management of software projects.
A key goal of development AntiPatterns is to describe useful forms of software refactoring. Software refactoring is a form of code modification, used to improve the software structure in support of subsequent extension and long-term maintenance. In most cases, the goal is to transform code without impacting correctness.
Architecture AntiPatterns focus on the system-level and enterprise-level structure of applications and components. Although the engineering discipline of software architecture is relatively immature, what has been determined repeatedly by software research and experience is the overarching importance of architecture in software development.
In the modern engineering profession, more than half of the job involves human communication and resolving people issues. The management AntiPatterns identify some of the key scenarios in which these issues are destructive to software processes.
This is a short and crisp article that takes you through some of the most important non functional requirements that an architect should never loose track of. The article shall help you understand each of these non functional requirement from SCEA exam point of view as well.
Non functional requirements also referred to as system level requirements or qualities of a system are one of the most important things that an architect should never loose focus on during inception and elaboration faces of the project. Of-course they come after the functional requirement as even the most robust, scalable and high performance system is useless if it not able to deliver the required behavior and functionality that is expected out of it.
In addition to the functional requirement of the system, it is the responsibility of the architect to work with the stakeholders of the system to define and baseline a quality of service measurement for each of the service level requirements. The architecture must address all the non functional requirements.
Depending upon the system domain and various other factors, an architect might have to make trade-offs between these non-functional requirements. This is perfectly fine, provided the stakeholders are kept informed and involved in decision making in this regard.
Following sections of the article briefly describe most of these non-functional requirements that you should address in your architecture.
The performance requirement is usually measured in terms of response time for a given screen transaction per user. In addition to response time, performance can also be measured in transaction throughput, which is the number of transactions in a given time period, usually one second. For example, you could have a performance measurement that could be no more than three seconds for each screen form or a transaction throughput of one hundred transactions in one second. Regardless of the measurement, you need to create an architecture that allows the designers and developers to complete the system without considering the performance measurement.
Scalability is the ability to support the required quality of service as the system load increases without changing the system. A system can be considered scalable if, as the load increases, the system still responds within the acceptable limits. It might be that you have a performance measurement of a response time between two and five seconds. If the system load increases and the system can maintain the performance quality of service of less than a five second response time, then your system is scalable. To understand scalability, you must first understand the capacity of a system, which is defined as the maximum number of processes or users a system can handle and still maintain the quality of service. If a system is running at capacity and can no longer respond within an acceptable time frame, then it has reached its maximum scalability. To scale a system that has met capacity, you must add additional hardware. This additional hardware can be added vertically or horizontally. Vertical scaling involves adding additional processors, memory, or disks to the current machine(s). Horizontal scaling involves adding more machines to the environment, thus increasing the overall system capacity. The architecture you create must be able to handle the vertical or horizontal scaling of the hardware. Vertical scaling of a software architecture is easier than the horizontal scaling. Why? Adding more processors or memory typically does not have an impact on your architecture, but having your architecture run on multiple machines and still appear to be one system is more
Reliability ensures the integrity and consistency of the application and all its transactions. As the load increases on your system, your system must continue to process requests and handle transactions as accurately as it did before the load increased. Reliability can have a negative impact on scalability. If the system cannot maintain the reliability as the load increases, then the system is really not scalable. So, for a system to truly scale it must be reliable.
Availability ensures that a service/resource is always accessible. Reliability can contribute to availability, but availability can be achieved even if components fail. By setting up an environment of redundant components and failover, an individual component can fail and have a negative impact on reliability, but the service is still available due to the redundancy.
Extensibility is the ability to add additional functionality or modify existing functionality without impacting existing system functionality. You cannot measure extensibility when the system is deployed, but it shows up the first time you must extend the functionality of the system. You should consider the following when you create the architecture and design to help ensure extensibility: low coupling, interfaces, and encapsulation.
Maintainability is the ability to correct flaws in the existing functionality without impacting other components of the system. This is another of those systemic qualities that you cannot measure at the time of deployment. When creating an architecture and design, you should consider the following to enhance the maintainability of a system: low coupling, modularity, and documentation.
Manageability is the ability to manage the system to ensure the continued health of a system with respect to scalability, reliability, availability, performance, and security. Manageability deals with system monitoring of the QoS requirements and the ability to change the system configuration to improve the QoS dynamically without changing the system. Your architecture must have the ability to monitor the system and allow for dynamic system configuration.
Security is the ability to ensure that the system cannot be compromised. Security is by far the most difficult systemic quality to address. Security includes not only issues of confidentiality and integrity, but also relates to Denial-of-Service (DoS) attacks that impact availability. Creating an architecture that is separated into functional components makes it easier to secure the system because you can build security zones around the components. If a component is compromised, then it is easier to contain the security violation to that component.