As developers work, they should always be looking for opportunities for code re-use. The software world is full of code re-use implemented in different ways. Such as libraries, toolkits, and engines. Developers can save time and resources, and often get proven, robust solutions by reusing code. Reusing code is much faster than developing new code. Even if code has to be modified or adapted to the application, it's still faster than writing from scratch. This is one of the many reasons that well-written and well-documented code is important. One way to harness code reuse for efficient development is to treat a group of products as a product line or product family. These terms are fairly interchangeable, so we will use product line for the remainder of the lesson. iOS is a familiar example to many people. iOS was originally called iPhone OS and was developed for the iPhone. But due to its ease of use and popularity, it was a natural fit for other touch-based mobile products like the iPod touch and iPad. The iPhone, iPod touch and iPad are an example of a product line. They all share the same operating system, so there is a lot of code re-use. However, there are important differences as well. The iPhone must implement telephone functions, such as connecting to cell phone networks, and making voice calls and SMS messages. The iPad has a larger form factor, so it uses different visual layouts and is also compatible with different external hardware. There are several reasons that a company may decide to develop a product line. The most obvious is cost. By reusing code between different products, the company has less development to do per product. This can mean less money spent on development overall. By freeing up development resources, more time can be spent testing for other quality attributes of the product, such as security and reliability. Less testing is needed per product, because the code that is reused has already been tested. But it is not just development costs or resources, another reason could be for user experience. If several products share characteristics, this means customers and developers can move from one to the other with less of a learning curve and fewer surprises. This may drive sales of other products in the same line. This is, in fact, a key strategy of Apple. Another reason could be time to market. If Apple decided tomorrow to develop a home management system with iOS on it, they could probably implement the software for it in a relatively short time. Because most of the software components are already made. These advantage, of course, do not come for free. The development hours needed for each additional product might be reduced, but some work is needed up front to develop the foundations for the products. What is shown here as an upfront investment. If you're only developing one or two products, it may not be worth it to treat them as a product line. That is, unless you plan on developing more products later on. As you develop more products the product line approach is more and more cost effective. The book Software Product Lines in Action, by van der Linden, Schmid, and Rommes, discusses the architectural considerations for software product lines. The first step in planning a product line is to separate the features that stay the same from the features that are different across products. Let's have a look. Commonalities, the features of the product line that stay the same in every product. Variations, the features of the product line that vary between products. Product-specifics, features that are specific to one and only one product. Commonalities stay the same between all products. This could be the visual elements, for example. Variations refer to features of a product line that are on some products, but not on others. If you were developing a line of tablets, a variation could be support for different cellular network connections. Product specifics are like variations, except they only apply to one product in the line. For this reason, they will be developed by the team that is responsible for that product. In your line of tablets, say you have one tablet that specializes in reading e-books. Its product specifics could be additional tools for managing e-books, and support for an e-ink screen. In terms of development, product line development teams are generally divided into two camps, domain engineering and application engineering. Domain engineering is the development of the commonalities and variations. Essentially this is putting together the building blocks of the products, or the infrastructure. Application engineering is actually developing a product. There could be several application engineering teams, one for each product. Application engineering includes using the commonalities, deciding which variations are necessary and integrating them into the product, and developing product-specific features. You may hear this described as instantiating a product, much like you instantiate a class in object-oriented programming. From a project management standpoint, separating development into domain and application engineering allows for separate development cycles. The domain engineering team can determine the long-term needs of the product line, evolve and test components as needed, then release that infrastructure to the application engineering teams. Once an application engineering team receives the infrastructure, and based on the requirements of their product, they develop product-specific features, decide what variations to use, and test the final product. This can be done while the domain engineering team is working on the next update of the infrastructure. The products in a product line will likely have very similar architectures, since by nature they serve a similar purpose. So instead of each product having an architecture, the product line usually has an architecture that the products build on or change. The domain engineering team is responsible for this reference architecture. The reference architecture is designed with respect to the needs of the software, except it now must take into account all the current products in the product line. The developers on the domain engineering team may also design with future products in mind. Because there will be differences in the product line, the reference architecture must also include the capacity for variation. There are three general techniques to realize variations in a system. In the adaptation technique, a component has only one implementation, but supplies interfaces to change or add on to it. One way to adapt the component could be through settings in a configuration file. Another way is to add new methods or override existing methods. You could also use the replacement technique. In this technique there could be a default component that is replaced with alternatives to realize variation. There may not even be a default. Instead there is a gap in the system, and the developers must supply one of the components. The extension technique is like adaptation, except that a common interface is provided for all the variations to the system. These are often called extensions, add-ons or plugins, like you would find in your browser or other desktop programs like Photoshop. Variations can be realized at different times, and different variations may actually come in at different stages. They can be formed very early on, such as during the design or development processes of the application engineering team. Variations can be formed when the software is compiled or built. Variations can be realized when the software is launched, like the plugins in your browser. They can even be realized dynamically after the software is launched when they're needed. Making your variations so dynamic puts heavy pressure on your architecture to be highly modular. The nature of the variation, the type of reference architecture, and the software requirements will drive what variation techniques are available to you and how they're implemented. As with any design decision, there will be trade-offs to make when considering how to build variation into the architecture. Product lines, or product families, are an efficient way to use the power of code re-use in related products. Developing your products in a product line and reusing code allows you to save time, per product, by doing more upfront development. Usually this is done by splitting development into domain engineering and application engineering. Product lines impose new requirements on the architecture. The reference architecture applies to all products in the product line, and it must handle both commonality and change. Designing this architecture and building in the capacity for variation will involve trade-offs, just like any other design decision. The extra resources and the common code in product lines can be used for all kinds of good. Reliability, user experience, security, time to market, and maintainability. Any developer with a product line of more than two products should consider this approach. >> Congratulations, you've gone through all the video content in this course. You've learned how to describe architecture visually. How to use a variety of common architectures. How to evaluate the quality of an architecture. And finally, how architecture relates to software development. Next up are the remaining capstone assignments. You'll practice the knowledge you just gained by documenting and explaining a system with a layered architecture. See you next time.