Welcome to the third module of the software architecture course. So far we've talked about the ways in which architectures are represented and communicated visually as well as various software architectures themselves. Now you're going to learn about how software architectures are analyzed, evaluated, and how they interact with software development. What makes an architecture good or bad for the given problem? How do we identify its quality and identify improvements? How can we use architecture to plan development and structure and development team? How can we realize opportunities for reuse to reduce costs and increase development efficiency? These are the practical kinds of architectural questions you will explore in this module. Let's begin. Software architecture aims to combine software design patterns and principles in order to define the software's elements, their properties, and how the elements interact with each other. We've explored the characteristics, qualities, and implementations of each design pattern and principle in the previous courses. We also looked at the various software issues that they address. It stands to reason that if the architecture of a system is just a set of design patterns and principles, then you can determine the capabilities and the quality of the architecture based on the various elements. However, this is not the case because design patterns are good at addressing one specific technical problem but are poor at addressing the wide range of business needs and concerns. Modern systems need to be able to address these problems as well, not just the technical issues. Therefore, system architectures are more concerned with addressing the bigger picture which includes functional and nonfunctional aspects of the system. An architecture will set guidelines for design patterns and principles in order to ensure the system has conceptual integrity so there's consistency throughout. Where individual design patterns and principles are concerned primarily with functional software issues, software architecture must also consider non-functional requirements. For instance, if we take a look at all the different design patterns that were introduced in the previous course there are a number of software qualities that they don't touch. For example, design patterns can improve a system's maintainability, reusability, and performance, but they don't address qualities such as testability, usability, and availability. Software architecture addresses these qualities by carefully structuring and coordinating design patterns in order to construct a unified system. Thus, the architecture of a system is qualified by how well the entire combination of software elements work together to provide functionality and handle potential system issues. In addition, the architecture is also qualified by how well the design addresses user experience and ease of development. Software architecture is not inherently good or bad. That is to say that an architectural design doesn't have inherent qualities that make it a good architecture or a bad architecture. Software architecture is designed to address a set of requirements. These requirements are used to address a problem or need. We've examined various types of system architectures in this course, and each one of them is meant to be used in different environments. For example, an online web based game will use an event-based architecture over a repository-based architecture in order to facilitate communications between players. This doesn't mean that a repository-based architecture is bad just because of its inherent design. It is bad because it simply isn't the correct design for the software environment. Not only would a database decrease the performance of your system due to the pace at which the state of the system is changing, but it would also be difficult if not impossible to allow for a large number of concurrent players. In fact, your system will most likely use a combination of architectural designs. The requirements for modern systems are complex and there may not be a clear cut software architecture that is capable of addressing all the requirements. The context in which you are designing is important. A system needs to be able to operate and perform within a given context. For example, if you design a system that is only capable of storing and processing a relatively small data set, you shouldn't expect it to perform effectively if the data demands exceed the amount that it was designed to handle. This would be like installing a human-sized door on your garage and then trying to drive a car through it. There are functional and non-functional requirements to consider when designing the architecture of your system. Of course the software must address all the functional requirements, but you also need to design to meet non-functional requirements as well. Non-functional requirements are not always clear or even explicitly presented by your clients or stakeholders. These requirements can also differ between each group of stakeholders. For instance, your development team will care about requirements like maintainability, reusability, testability, and supportability because they will be the ones that will need to support the system during its life cycle. An end user most likely doesn't care about testability, but will care about ease of use, error handling, system stability and so forth. Be mindful that different groups of stakeholders have different expectations. Your software architecture should address the concerns of each group. Prioritize the system requirements and don't be afraid to make compromises in order to find a good balance between system qualities. How would you measure an architectural design to determine if it is capable of meeting the system requirements? The quality of a system is determined by quality attributes. They are measurable properties of a system used to gauge a system's design, run time performance, and usability. In order for an attribute to be measurable, you need to have some objective method of quantifying it. For example, system availability can be measured by the system's uptime in some unit of time. What is presented in this lesson is the industry consensus for quality attributes, but these are not set in stone. You can add or remove quality attributes from your evaluation of a system architecture based on your specific needs. We have placed an emphasis on maintainability, reusability, and flexibility when designing and implementing systems. It shouldn't be a surprise that these characteristics are part of the set of quality attributes used to assess the design of a system. Maintainability determines how easy systems can undergo change. Your system will undergo many changes throughout its life cycle in order to fix errors, change software elements, add new features, or retire old services. Any system that you design should be able to accommodate these changes with relative ease. Reusability allows you to take functionality or parts from a system and use it in another system. It helps reduce the cost of reimplementing something that has already been done. Flexibility is a measure of your system's ability to adapt. A highly flexible system is able to adapt to future requirements changes in a timely and cost efficient manner. Modify ability is closely related to maintainability in that it is a measure of your system's ability to change. This quality attribute determines the ease at which your system is able to handle changes to functions, incorporate new functionality, or remove existing functions. The goal of a highly modifiable system is to provide an enhanced experience to the end user by adopting new technologies and industry standards. However, it is also the most expensive design quality to achieve so you must take into consideration the costs associated with implementing changes. Questions that you may have are: what can change, who will be making these changes, and what are the possibility of changes happening? Your system should also have high testability. This is defined by how easy it is to demonstrate errors through executable tests. Programmatically testing your system for errors is important because they can be done quickly, easily, and do not require a user interface. Testing during implementation will help identify faults so that they can be fixed before you release your system. Finally, the system architecture should have conceptual integrity so that there is consistency throughout the system. This can include consistency in design across subsystems through naming conventions. Quality attributes for design are important because they carry through the design phase into the implementation and support phases of your software's life cycle. Of course, at the end of the day, the quality of your system will be most dependent on how well it performs. Is it able to meet requirements? Is it intuitive to use? Does it perform its functionality in a timely manner? Are the outputs of the system correct? How well can it handle errors? There are many qualities to take into consideration when evaluating how well a system performs from a user's perspective. Let us take a look at what these quality attributes are and what they are measuring. An important quality of a system is its availability which is the amount of time the system is operational over a set period of time. The reason a system's availability is measured by its uptime is because you want to know how well it is capable of recovering from issues such as system errors, high loads, or updates. Your system should be able to recognize and try to prevent these issues from causing downtime. Interoperability is the extent of your system's ability to understand interfaces and use them to exchange information under specific conditions with external systems. A system's interoperability is measured by how well your system is able to recognize and respond to other systems as outlined in the semantic documentation that describes how communication and information sharing should be handled. Most modern systems are interoperable and do not exist in isolation. They must be able to exchange information with others and be able to interpret the data that is being exchanged. A well-designed interoperable system has a defined context in which it exchanges information. This includes communication protocols, data formats and with whom the system is allowed to exchange information with. The security of your system is how well your system is protected from unauthorized access and use. Modern systems generally contain sensitive information about a business or its clients. This information should only be accessible to end users that are authorized to see it. Furthermore, sensitive data should also be readily available only to those with authorization and the system should provide data integrity. This means controlling who can see the data versus who can also change the data. Performance determines how well your system is able to respond to a user command or system event. It is measured by the system's throughput and latency. Throughput is the amount of output produced over a period of time while latency measures the time it takes to produce an output after receiving an input. This quality attribute has historically been very important to users. Therefore, it has a major influence on architectural design. When you measure your system's performance, you want to have a lower price per unit of performance. With the advancements in technology, this ratio has been steadily decreasing. Finally, usability determines how well your system is able to address the requirements of the end users. In order to have high usability, your system needs to be easy and intuitive to learn, minimize user errors, provide feedback to the user to indicate that the system has registered their actions and make it easy for the user to complete their task. You aim for your system to provide a high quality user experience so your users will want to use it. Even if you have the most sophisticated system on the planet, an end user will avoid it if the experience is intolerable. Now that we have examined the quality attributes of a systems architecture, how do we go about designing a high quality system. Since software architecture is not inherently good or bad, what really matters is being able to create or choose an appropriate architectural design for your system. This is important because the architecture is what will ultimately determine how functionality is implemented, how subsystems communicate with each other and how end users will interact with your system. Imagine spending thousands, if not millions, of dollars and person hours on a system that does not solve the problem it was supposed to. Now a company would need to decide if they want to keep and use the system as is, spend more time and money on fixing the issues or scrap the software altogether. Another reason that software architecture is important is because it makes maintaining, supporting and updating the system throughout its life cycle much easier. If the qualities achieved by the architecture are relatively poor, then it will be difficult for you to support changing needs. Software architectural design or selection should be a meticulously planned process. You should not randomly select and implement architecture, then make changes and hope for the best. A high quality system does not need to be complex. More often than not, an overly complex system makes it more difficult and time consuming to produce. Thus if you are able to produce a high quality system while minimizing the complexity in the design, then it is usually better. If a simpler architecture can satisfy all the system requirements and achieve a high quality design while needing less time and less money, it makes sense to go with that. Another important part of producing a high quality system is to have detailed and up-to-date documentation. This will allow you to disseminate the architectural vision to your coworkers so that they know how the functionalities of the system are designed and how each software element interacts. The architectural knowledge of your system should not reside with just one person. If this person decides to leave the company, go on vacation, retire, fall ill or meet a tragic end, then the development of your system can be in jeopardy. Having detailed and current documentation of your system helps prevent time and money from being wasted should something happen to the architect. The process of designing a high quality system architecture should be methodical. You should use a set of rules or guidelines for the design process and how your system will be structured. While the design rules or system structure rules vary from company to company within the industry, some of the more general rules should be common sense. Some design process guidelines include recognizing the importance of quality attributes and prioritizing them for each system being designed. The identified quality attributes should be kept up to date throughout the lifecycle of the system. Each quality should also include details as to how the system will meet them and should note any tradeoffs under various circumstances, involving a technical lead in the design process. With a number of different technologies available today, it is unrealistic to be an expert in all of them. While architectural design can be applied to many different technologies, the implementation may pose enough of a challenge that some design decisions may need to be reconsidered or re-evaluated. Having a technical lead take part in the system design will help with spotting these difficulties and provide the knowhow needed when transitioning from design to implementation taking a design approach from the perspective of different groups of stakeholders. This can help ensure that your system will be able to address the needs of everyone that is involved. You can also create structural rules which are used to ensure that there is conceptual integrity when implementing your system. Some examples of these rules are having well-defined subsystems that are assigned responsibilities based on design principles. You should be practicing design principles such as separation of concerns or information hiding when designing the subsystems of your system architecture, having consistent implementations of functions across the entire system. If two or more subsystems need to achieve the same task, then the implementation of how to do the task should be reused throughout the entire system, having a set of rules on how resources are used. Resources can be but not limited to memory, bandwidth or threads that the system has access to. You want to have a well defined set of rules on how the system utilizes its resources. For instance, bandwidth can be prioritized for customer transactions over queries in an online store. There are many factors that play a role in determining the quality of your system architecture. A system's quality attributes help you to measure and gauge how well designed your software is and guide you in your design decision making. Remember that architecture is not good or bad. It is a matter of selecting the appropriate architectural solution for your problem. You should consider involving all groups of stakeholders in the design of your system so that all concerns are heard and addressed, adopting good documentation practices to ensure that the details of your system design are not lost over time, setting rules for design and implementation so that you are able to achieve high standards for your quality attributes. A properly designed system will consider quality attributes that address the developers' perspective by providing maintainability, reusability, flexibility, modifiability, testability and conceptual integrity; the users' perspective by being available, interoperable, secure, performant and usable.