CA Flashcards
What is software architecture?
Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change.
What is good architecture?
Meets the needs of its users, developers, and owners at a given point in time, but it also meets them over time.
The path we are most interested in recognizes the softness of software and aims to preserve it as a first-class property. Architecture is a hypothesis, that needs to be proven by implementation and measurement.
What is the goal of software architecture?
To minimize the human resources required to build and maintain the required system.
The measure of design quality is simply the measure of the effort required to meet the needs of the customer. If that effort is low and stays low throughout the lifetime of the system, the design is good.
What does increased engineering staff but stagnated product size indicate?
That the cost per line of code has changed over time. The trend is not sustainable and will cut into the profit of the business model.
Effort has been diverted away from features and is now consumed with managing the mess.
Making a mess is always slower than staying clean, no matter which time scale we are using. The only way to go fast, it to go well.
The solution is not to redesign everything from scratch, the same overconfidence that lead to the mess will lead to the same mess again.
What are software engineers hired to do?
Make machines behave in such a way that makes or saves money for the stakeholders. This is done by helping stakeholders develop a function requirements specification and implement it, when something goes wrong the bug is fixed. The other half of their work is to fulfill the purpose of software, namely, being soft - that is easy to change.
How easy should changes be in software?
A good architecture makes the difficulty of implementing a change proportional to its scope, not the type of change.
It is this difference between scope and shape that often drives the growth in software development cost.
The more the architecture prefers one shape over another, the more likely new features will be harder and harder to fit into that structure. Therefore architectures should be as shape agnostic as practical.
What is Eisenhower’s matrix?
Matrix highlighting importance versus urgency.
- Urgent and important
- Not urgent and important
- Urgent and not important
- Not urgent and not important
The behavior of software is urgent but not always important. Architecture is important but never urgent.
The behavior of code occupies the first and third positions, but the mistake project leaders and developers make is to elevate the third position features to first. This failure leads to ignoring the important architecture of the system in favor of the unimportant features of the system.
How are software development like science in relation to tests?
Tests shows the presence, not the absence of bugs. A program can be proven incorrect by a test, but it cannot be proven correct. Testing deems a program correct enough for our purpose.
Similar to scientific theories since they are falsifiable but not provable.
It is the ability to create falsifiable units of programming that make structured programming valuable today.
Software architects strive to define modules, components and services that are easily falsifiable.
What is polymorphism at its core?
An application of pointers to functions. The problem with explicitly using pointers to functions to create polymorphic behavior is that pointers to functions are dangerous. This difficulty is solved by OO languages my making it trivial to create polymorphic behavior.
What does polymorphism provide?
Control over the direction of all source code dependencies. We can invert dependencies such that modules can call into other modules without mentioning anything specific, this provides independent deployability and development.
This is also very important for creating testable programs.
Why is immutability interesting to architects?
All concurrency issues we face, race conditions, deadlocks and concurrent update problems are due to mutable state. With immutable objects we will not face any problems related to concurrency.
What is segregation of mutability?
Segregation of the application or services into mutable and immutable components.
Since mutating state exposes the mutable components various problems, it is common practice to use some kind of transactional memory to protect the mutable variables from concurrent updates and race conditions.
Architects would be wise to push as much processing as possible into the immutable components, and drive as much code as possible out of those components that must allow mutation.
What is event sourcing?
More ram and faster processing speeds equals less reason to use mutable state. Event sourcing stores transactions and current state is retrieved by calculating all these transactions. We can optimize this a bit by calculating a starting point state every midnight.
Transactions are never deleted we only ever use create or read. Hence systems become entirely functional.
What do the SOLID principles tell us?
They tell us how to arrange our functions and data structures into classes and how those classes should be interconnected. The SOLID principles apply to groupings of functions and data not just OOP classes.
What are the goal of the SOLID principles?
To create mid-level software structures that:
- Tolerate change
- Are easy to understand
- Are the basis components that can be used in many software systems
What are the SOLID principles?
S (SRP, the single responsibility principles): Each software modules should only have one reason to change.
O (OCP, the open-close principle): For software systems to be easy to change, they must be designed to allow the behavior of those systems to be changed by adding new code, rather than changing existing code.
L (LSP, the Liskov substitution principle): To build software systems from interchangeable parts, those parts must adhere to a contract that allows those parts to be substituted one for another. Objects of a superclass shall be replaceable with objects of its subclasses without breaking the application. That means you can implement less restrictive validation rules, but you are not allowed to enforce stricter ones in your subclass.
I (ISP, the interface segregation principle): Do not depend on things we do not use.
D (DIP, the dependency inversion principle): The code that implements high-level policy should not depend on the code that implements low-level details. Rather details should depend on policy.
What is the single responsibility principle?
SRP is about functions and classes - but it reappears in a different from at two more levels. At the level of components, it becomes the common closure principle. At the level of architecture it becomes the Axis of Change responsible for the creation of Architectural Boundaries.
A module should have one and only one reason to change. Or a module should be responsible to one and only one actor (group of users or stakeholders).
Problems can occur when we put code that different actors depend on into close proximity. The SRP says to separate the code that different actors depend on.
What is the Common Closure Principle?
It states classes which are close to the same type of change should be put in the same component. In other words, classes which change because of the same reason and at the same time belong to the same component. Vice versa, classes which change because of different reasons and at different times should be in different components.
What is the open-closed principle?
A software artifact should be open for extension but closed for modification. If extensions to the requirements force massive changes to the software, then the architects of that software system have engaged in a spectacular failure.
OCP at the architectural level works by separating functionality based on how, why and when it changes, and then organize that separated functionality into a hierarchy of components. Higher-level components are protected from the changes made to lower-level components.
Note, transitive dependencies are a violation of the general principle that software entities should not depend on things they do not directly use.
What is the Liskov substitution principle?
LSP has morphed into a broader principle of software design that pertains to interfaces and implementations, in relation to its early days where it mostly concerned inheritance.
A simple violation of substitutability can cause a system’s architecture to be polluted with a significant amount of extra mechanisms.
What is the interface segregation principle?
ISP in architecture refers to the dangers of depending on modules that contain more than we need. Depending on something that carries baggage that we do not need can cause troubles we did not expect.
What is the dependency inversion principle?
DIP tell us that the most flexible systems are those in which source code dependencies refer only to abstractions and not concretions.
We tend to ignore the stable background and platform facilities when it comes to DIP since these classes/modules rarely change. It is volatile concrete elements we want to avoid depending on.
Good software designers and architects work hard to reduce the volatility of interfaces. Stable architectures are those that favor the use of stable abstract interfaces.
What implications comes with DIP?
- Do not refer to volatile concrete classes. Refer to abstract interfaces instead.
- Do not derive from volatile concrete classes
- Do not override concrete functions
- Never mention the name of anything concrete and volatile.
What is an architectural boundary?
It separates the abstract from the concrete.
What are components?
They are units of deployment. They are the smallest entities that can be deployed as part of of a system.
Components can be linked together in a single executable, they can be aggregated into a single archive such as a .war file. Or they can be independently deployed as separate dynamically loaded plugins such as .jar or .dll.
They always retain the ability to be independently deployable and therefore independently developable.