Product architecture is a visual representation of a product, which provides a common understanding of how the product is organized and shows how different parts relate to each other. It describes the product at conceptual level and can be used as an input for further product development methods / activities such as design, engineering, or testing.
Most often it is depicted as a block diagram where:
– boxes represent functional modules (components) and describe what they do;
– arrows show possible interactions between components and typically control flows are shown by solid lines while data flows are dotted ones; obsolete modules are drawn in gray color. Sometimes these diagrams may also include additional information on the runtime environment, languages or protocols used.
Examples for some types of product architecture are given below. For more examples see the list of software architecture styles.
Architecture description languages (ADLs) are formal languages for representing and documenting architectures. They vary in the degree to which they specify implementation details such as programming language syntax or runtime information such as object locations, communication protocol or naming conventions. The earliest ADL was the “Applied Data Flow” language developed by Barry W. Boehm’s TRW in 1974 to document main memory interactions between programs executing concurrently on a shared computer system. ARIS is an example of specification-level ADL that assists with all stages of architectural work including design, documentation, validation and verification. AspectJ is an implementation-level ADL that aids programmers implement modularity in Java systems while controlling incidental complexity arising from crosscutting.
Detailed knowledge about the structure of an implementation is useful for many purposes, including support by tools during development or debugging. The term “ADL” was popularized in the late 1990s when IBM and Microsoft made their proposals for “architecture descriptions”. These ADL were designed to bridge between higher and lower levels of abstraction:
For example, C/C++ programmers must manually manage multiple execution threads, whereas Fortran programmers can use available language features directly. Similarly, Java programmers must manually manage memory allocation and deallocation while C# programmers do not have such responsibilities. In both cases, ADL can be used to maintain compiler-level information related to these two languages when they compile code written in conformance to the systems’ specifications.
ADLs are proposals for improved language integration, but they do not work without additional effort. When interoperating with languages using ADLs, it is necessary to map between two levels of abstraction. This is difficult because many compiler optimizations exploit the fact that source code’s meaning changes as it is compiled into machine instructions or other forms. Furthermore, there are multiple stages before compilation even begins where transformations occur that reduce language integration flexibility due to information loss. For example, if a C++ “header file” (e.g., codice_1) needs to be referenced by another C++ source file (e.g., codice_2), and both files need access to a common subset of types and functions declared in a third source file, codice_3, it is necessary to define this commonality as well as the relationships between the types and functions before any compilation can take place. This often requires writing meta-comments manually, which amounts to mechanical transformation from one representation of information to another.
In this example, there are three C++ source files that must be compiled into machine code or some other form. In order for a compiler to compile a higher level file into a lower level file (lower being whatever denser representation is closer to machine code) various language mapping strategies have been developed over time. One such strategy where the difficulty lies is in the multitude of transformations that must be for between each successive step from high level to low level. A compiler is said to have a high barrier of entry because of the amount of domain knowledge that must be inside the toolbox before it can be used effectively. A second problem is there are many different types of transformations between successive file formats, which means mapping strategies are not uniform across languages or domains. This leads to both problems one at large plus the lack of uniformity in how users are supposed process information within each domain leads to further problems when doing meta-tasks on multiple domains as now another set of unique mapping strategies needs to be included in any learning strategy if generalization across domains is desired. As such machine learning does not benefit much from C++ as a lot of domain knowledge cognitive load needs to be mastered before use in actual problem solving.
C++ is often criticized for having an overly complicated programming model, which leads to various levels of errors when used improperly. These issues are regularly found in large-scale projects (e.g., Chromium). To cope with this, C++ mandates careful attention to detail within the standard; see C++ Core Guidelines for details. That said, modern approaches like Modern C++ and concepts employed by template metaprogramming assist in writing simpler code with fewer errors over older techniques like macros.