Contents
Architecture and other Metaphors
Architectural Forces
When do you need an architect?
Why software architecture?
Course Overview
De Architectura
Durability the building should last for a long time without falling down on the people inside
Utility the building should be useful for the people living in it
Beauty the building should look good and raise the spirits of its inhabitants
Vitruvio, 23BC
For example, one of the basic ideas of Architecting Buildings
is that you should know how to design a building that can last for a
long time. There are buildings from thousands of years ago that are still standing today. They have only been built using stones. As with every technology that you choose to adopt. You should know the
limits and you should know when it's applicable when it's not. You should be confident that the building will not collapse while or after attempting to build it.
The second principle is that what you built
should be something useful. A bridge which connects two sides across a river, making it possible to cross it.
A house for people to live in. A university with classrooms for students.
The third one concerns the effect of the building on the people inside. Does it provide a welcoming place for people to live inside? Do people enjoy working in it? Or do people want to escape from it as soon as they can?
The Art and Science of Building
Architects are not concerned with the creation of building technologies and materials—making glass with better thermal qualities or stronger concrete.
Architects are concerned with how building materials can be put together in desirable ways to achieve a building suited to its purpose .
The design process that assembles the parts into a useful, pleasing (hopefully) and cost-effective (sometime) whole that is called “architecture”.
Architects are not
concerned about how to create new and improved building technologies. They are also not concerned with the actual construction of the building themselves.
They're mostly interested
about how to select and compose the right tools, introduce the right elements and connect them appropriately. How to establish the right kind of
relationships between the
elements so that we have a good
building that fits its purpose?
While doing this, the
architect is making the
decisions for the building's plan, which will be executed to construct the building by someone else.
If you learn how to be an architect,
you need to learn how to plan.
And you will learn how to do it
before the actual building exists.
The same holds for a software architecture, full of ideas that you
should be able to express in your
design for the software before
it's being built so that someone
else can go and write the actual code for it.
As experienced individual developers, you may wonder how this works, where does the architect fit between the customer requirements and my work writing the software?
Well the architect is key to be able to lead the development effort and scale it so that you can have hundreds of developers working on the same project. And making sure these developers agree on how the architecture for this code should look like.
Overall this is what we call architecture: a kind of design process, with selection and composition activities, but also a process rather different to simply writing and testing the code.
Architecting, the planning and building of structures, is as old as human societies – and as modern as the exploration of the solar system
Architects follow a process going from a concept, represented with sketches, which are refined into mockups and detailed plans, which can then be built. A successful result of the whole process will embed and highlight the original concept.
Following such process helps to catch and correct mistakes early, explore different options, validate the concept also in relationship with its context (no city building exists in isolation from the ones surrounding it). Likewise it helps to obtain buy in from the customer, who can attempt to influence the outcome of the process.
You should learn how to sketch the architecture of a software system. You should learn how to refine your sketch and
make it into a plan so that somebody
else can write its code.
Foundation
Another concept that we
borrow is the idea that when
we build someething, we need to have a
foundation for it. This is
the point of contact with the ground, the surface that
supports the building.
Also when you write your
software you are building it on top of a foundation made of software and hardware.
It is important to be aware about the kind of foundation you select to deploy your software on.
Nothing is built on stone; all is built on sand, but we must build as if the sand were stone.
Jorge Luis Borges
Successful platforms last for a long time. Successful platforms attract developers, who flock from platform to platform. Unsuccessful platforms are discontinued as it is not economically viable to maintain and provide support for them. Platforms also evolve as their underlying technology improves, gets faster and cheaper. Planned obsolescence on the other hand is used to quicken platform upgrade cycles by force so that it becomes possible to make platform adopters pay again and again, especially when there is only one platform left in the market.
Eventually you come to the realisation that there is
nothing that is built on a solid
foundation. Everything is built
on shaky ground. But we have to
pretend that when we decide to
invest into building a piece of
software, we can do so by reusing some kind of a platform and trusting or hoping that it will remain there long enough.
It is no longer feasible for a single developer to design their hardware, define a processor instruction set, build their own computer, invent a programming language, write a compiler, a standard library for it and use it to write the operating system for such computer, and still have enough time left to write useful apps to run on it.
Closed
Other
metaphors
that we that we use when we talk
about architecture is for
example, the notion of boundary.
The first thing you should define is the system's boundary, for example, by drawing a box delimiting the inside of your system from the outside, the rest of the world.
This boundary can be closed, if your system is isolated and does not exchange any information with outside. You have
complete knowledge about the
state of the system and there is
no information that you have to
go somewhere else to get.
Another way to look at the closed metaphor is to consider the functional requirements that the closed system should satisfy. For example, let's consider the game of chess or the game of go.
You can list the rules, you know
exactly what they are, and the
rules are not changing. And these rules are limited and
well known in advance.
This makes it possible to solve the game.
Open
Your system is no longer closed the moment that you have
uncertainty about its boundary. Not only requirements may be partially known, but they may change in the future in unexpected ways.
Let's say you build a application and you publish it on the open Web and it goes viral. A few days after you launch, you get 2 millions of users that you did not anticipate. But what if it never happens? Should every architecture be designed to scale to "Web scale"? Or is it more important to be able to grow and adapt your system when it becomes necessary?
Also, the moment that you have something called the Internet, everything becomes connected to everything else. Today every system is an open system. Whether you want it or not, you cannot build a wall around your system, it needs to be integrated with other systems to be useful. Your system becomes interdependent and
interconnected to other systems over which you have no control. Service providers may disappear without notice or change their terms of service (e.g., switching from a free to a paid service, or a stiff price increase), making it no longer possible for your system to work with them.
Interfaces
When we have open systems which
connect with other systems, the points where their boundaries interact become very important. We call these interfaces and will dedicate some time to dissect the issue of how to build a good API.
This biological picture represents a slice through some vegetable which has cells that are quite large. Every cell has a boundary and an interface towards the other cells. Life has taken a long time to find out how to evolve from single-celled organisms into multi-cellular ones.
It is not a trivial problem for heterogeneous, autonomous and distributed systems to communicate, interact and inter-operate so that you can use them as building blocks to construct something larger, something whose value is greater than the sum of its parts.
This becomes particularly difficult when each system is built by people who do not know one another and are unable to talk together and have a tendency to apply changes without informing the others in advance.
Forces
What are the
challenges of designing an
architecture that as an
architect you have to deal with?
Your architecture should be useful: how do you find out exactly what the requirements are? What's the
problem that you are supposed to
solve? It is usually not your problem, but it belongs to someone else: how do you talk to your customer in
the right way so that you can
understand what they want you to do?
Since software can be applied
across any domain, this is particularly hard, unless you become an expert in the particular domain.
Assuming you understand what you need to solve, and assuming you can solve it with software. Will you be able to do so within a budget? Can you build it within a reasonable amount of time and by spending not too much money? Can you always speed up your project by adding more developers to the team?
Be careful not to fall into the mythical man month trap.
Once you have a reasonable budget, you still need to pick a suitable technology platform. Learn more than one technology, and be critical and aware that every
technologies that you choose
will have some limits and these
limits will affect where it is
applicable and where it should not be applied. And the choice of an expensive technology will impact on your budget, or an immature or unknown technology will reduce your team productivity. Although developers tend to be motivated to play with shiny new tools.
Finding a viable, feasible and desirable solution is also what engineers do. The difference with architects is their focus on making the solution as simple and elegant as possible. Everything else being equal, never underestimate how challenging it is to find an essential, beautiful and simple architecture. This is something worth striving for, even if it may not so obvious what makes a piece of software beautiful. Even if you should have enough experience to tell the difference.
For example, interfaces may be used to hide the ugly internal details. And developers will enjoy or hate working with a certain language or library. You can help them to
come to your platform if you make it simple and easy for them to learn. However doing this is hard.
When do you need an architect?
It depends.
Is it a first-of-a-kind project? Or is it something your team has done many times before?
Also, it depends on how large and complex your software is going to be.
Small
One Person can build it
Minimal planning
Basic tools
Simple process
Medium
An experienced team can build it
Modeling plans
Power tools
Well-defined process
Large
Do not try this without an architect
Ultra-Large
Was this designed by an architect?
How Large?
Always choose the appropriate tools for the size of the project you are working on
When you start a project
ask yourself how large is going
to be and how long is it going
to be alive for?
And then choose the right team
organization and choose the
appropriate tools to do it.
How Large?
How much time to build it?
How many people in the project?
How much did it cost?
How to measure software size? Lines of code (LOC) , GB, $
There are many different ways
to measure the size of software. For
example, you can ask:
How long does it take to build
it? And this is actually quite
ambiguous, you can define it as
the development wall time, starting from first Git
init command where no code exists yet and
then checking how long does it take you to write all the code. Or if you are using DevOps and
continuous integration. How long
does it take to build it and release it?
I push a change and then I go
home and come back the next
morning and I have the fresh new build. Or
I push a change and I can see
the effect instantaneously like with a live programming environment. It's a totally
different developer experience.
Small systems can be written by one developer, but most are written by teams. You can have larger and larger teams, but how do you organize 5000 people working on the same system?
What is the largest software project you have been working on?
How Large?
Software Architecture
As the size and complexity of a software system increase, the design decisions and the global structure of a system become more important than
the selection of specific algorithms and data structures .
As the size and
complexity of your software
grows, there is something that
becomes gradually more and
more important than just knowing
what is the algorithm or picking the data structure. Going back to the building metaphor, this would be like the choice of the type of electrical wires, plumbing pipes or window glass.
Lecture Context
Most of the courses you have studied give you the impression that you will build everthing every time from scratch. Design a new database schema. Write a new program.
The real world is not like this.
You don't often go into a software company to write your application from scratch. You work on their
existing code and the existing
code can have millions of lines.
And what you build is usually an
extension or an
integration, a new piece that
connects with other pieces.
We assume that you know how to build individual parts, but once we have all these
components. How do we
integrate them? How do we
connect them so they can work together? In this lecture we
talk about the big picture.
Why Software Architecture?
To motivate the need to learn how to
work with software architecture, we need to place ourselves in the right context, where there is one or more team of developers working on a large piece of software. How do we keep this alive and well but also under control?
Hiding Complexity
You should be able to work
with powerful concepts that
underneath have a lot of
information attached. But you can talk about them
because you learned how to use
the right technical terms that
can help you to describe
something that is complex
in a very compact way.
Abstraction
The difficult part is to know which elements to leave out and which to emphasize
In the geography domain, you have a satellite picture or
you can have a map.
And, which one represents the territory,
the real thing?
When
we build a model we are trying
to Capture the information that
is necessary for us to solve
certain problems for example,
here we have a street map. And you want to know, how to I go from A to B? Should I take the highway?
The difficult part when you
do abstractions is to know what
information do you keep in the
model in which information can
you ignore. When you draw a
picture of your software that
has 1,000,000 of lines of code.
You have to decide which lines
are important, and which lines
are not which ones should I
visualize and which ones I
shouldn't.
In the example, we have 3 different representation, which when doing an architectural model we call viewpoints or perspectives. They show different aspects of the same architectural model. It's important that all representations, while showing different aspects, are consistent. Otherwise, the developers that
look at one map will do
something different than the ones looking at a different map, because they read an
inconsistent message about the system they are trying to build.
Of course at the end of the day,
the code is the ultimate source
of truth about a software system. What you write in the code
embeds all decisions that were made to design it.
However, how can you gain an understanding of millions of lines of code? It is impossible to read every single one.
This is where using abstraction to manage such complexity helps. You can see the software architecture as a map to navigate large amounts of code.
Communication
A second very important
aspect of architecture is about
enabling the communication
between different team members.
The goal is to have an agreement
between the developers about
what to do so they will build
the same system. They will write
code that can be integrated
together.
But also there is a need for communication
between the customers and the
business side of the world or
the domain experts and the
technical people. The architect
is the point of contact, who
should be able to
translate back and forth.
As architect, you have to be an expert in the
technology, you need to know how
to talk to a developer an be
able to tell him how to build
the software, but also you have
to be able to talk to the
business side and explain why
you need certain amount of time
to do a project or why do we need to
pay so much money to so many
developers. So this may be
challenge because if you
just study software and data engineering, you
are very strong on one side but do keep in mind that as an architect you need also to
be able to bridge this gap.
Representation
Architecture visualization
was born with those famous boxes
and lines diagrams.
Sometimes the discipline is
criticized because it seems architects
spend their time drawing and looking at
these diagrams. How
is that connected with real software?
However, when you have very
large software, the argument is
that it's important for describing and understanding it, to be able
to represent it. Not by using a
programming language, but using
some kind of a diagram which follows some
kind of a visual notation.
There are many notations, UML is
not the only one. This one is more like a data flow diagram, showing how data is transformed while in transit between different storage elements.
Whatever notation you choose, the
visualization works if it tells
you a story. If it explains you
how the software works and how
it is built so let's
look at this example.
You should be able to tell me
the name or at least the purpose of the system.
A search engine? Yes, Why?
It shows many
individual functions (the bubbles) that you
would expect to find in such a
system and also, if you
look at the overall flow, there is a loop for crawling the Web and everything leads down into to the searcher.
Between some functions you have state (the barrels) which functions read from and write into.
Why are there so many barrels? Because it is important to show at this architectural level that the index is huge, so probably they use sharding and also need to have fast access to it to improve the search query performance.
Exactly which search engine is this diagram representing? This is actually an early picture of Google, you can tell by the "Pagerank" bubble, which takes the Web link topology into account when ranking the search results. This was their key innovation, sometimes it is enough to add one new component to an existing architecture to make a difference.
Visualization
There is of course,
the whole branch of software architecture
visualization out of which the
layer cake is one of the most
famous examples.
This is also the classical
sway to explain in the
connection between operating
systems and applications, the different roles of
user space and
kernel mode and illustrate how hardware is abstracted away through several layers of software.
This type of
visualization also shows
this concept of the foundation on which your application are built on. User programs use
the
services provided by the "underlying"
infrastructure. What is also
important in this picture is
that every point of contact
between the layers becomes
an interface.
Choosing a layered architecture, gives you a fundamental way not only for subdividing
the system but also for
deciding how the
different parts are connected
together (and which parts cannot be connected) and what kind of interfaces do they should provide.
Visualization
Another layered architecture, a bit simpler than the previous one. This is the type of picture that you would see if you join the company, to give you the overview when they start explaining you the architecture of their system.
What system does it represent?
Something
online, because there is a
Web Server. Something that needs to scale to handle lots of users, because there is a load balancer. Since it mentions PHP, it could be Facebook.
These are all valid guesses, but independently of the actual name of the system, we can look at the diagram and think about what are the most important concerns for the architects that designed it. How can this describe Facebook without mentioning the social network graph of friends? Well, this picture tells a different story. It says we have billions of users and we need to scale. We need a load balancer, we use PHP (but we rewrote the compiler to improve perormance), we use a database, but we put a memory cache in front of it to speed up read operations. If you are the architect in a company that went from 0 to billions of users in a short time, your core concern is how to scale.
This scalability problem is one of the many possible qualities that you should worry about as an architect.
Quality
You may have heard about the difference between functional and non-functional requirements. If you satisfy the functional requirements you have a correct system. If you satisfy the non-functional requirements, you have a non-functional system, a system that doesn't work.
In this lecture, we use the term "extra-functional" requirements, to describe all qualities of a system that go beyond its basic correctness. A functional system works, but how well does it work?
If you want to satisfy your customer, delivering a correct solution is a necessary, but is it sufficient? What if you deliver a super scalable solution (like in the Facebook example) but you forget to implement the "invite a friend" feature?
How do you write a programz
that is correct? There are
plenty of lectures where you can
learn that, so I assume that you
know how to do that. What we're going to do
here is look at everything else.
For example, once you
deliver it to the user,
your software should be usable. You can study
human computer interaction to learn how to
and how do we design user
interface which
takes advantage of what the
hardware can do (e.g., keyboard
and mouse, touch, VR/AR, or voice) and choose the appropriate ones for the type of system you are going to build.
What happens if something
is not usable?
Well people need to be trained.
So it's more expensive to start
using the system because people
cannot use it by themselves,
they need to go to a training
course.
However, when users get in
trouble, they ask for help; so
how easy is it to support your
user? Do you have the
way to actually see what they're
doing in the system and then you
can help them better. How easy this is depends on the way that you
designed your system.
Another quality is how expensive is your software going to be. Are you going to
sell it for a certain price. If
you give it away for free, then
you don't make any money with
it. How are people supposed to
be supported while using it? Or In other
words, if you have a business
model where the software is
free, how are you supposed
to pay the salaries of the developers
that build and maintain it?
It's also an important decision: What's the business model
behind your software? Do you
offer free software or people
have to pay do you have a one
time license or do you pay every
subscription every month? If you don't
write the software and sell it
to end users, but you write a
component and that component is
sold to be used within other
systems and then you can also
sell it and get royalties. You
can also sell it as a service
and people pay you and then
depending on how much traffic
they send you then you charge
them in your monthly bill.
This is what happens with service oriented and
cloud computing.
Resilience determines how
easy it is for you to keep
maintaining the system. For
example, when a user tells you
there is a bug. How much work does it take to fix
it? Or they have a new feature
requests, how easy it is to extend
the system? What is the impact of change within
your architecture? Maybe you
have designed and built the perfect system.
But you should never
touch it again.
Because it's not possible to
change it. Maybe you lost the
source code, maybe the system is
still working fine, but nobody
has the source code anymore.
So you need to call the
reverse engineering consultants to do the retrofitting.
Another aspect that is different
than usability is how reusable
is your software. What is
easy to use for a certain
application, may be difficult to reuse for another one.
And usually when you make it
reusable, it tends to be very general. You
can transport it and you apply
it in many different context,
but then it's more complex.
Because it has a general
interface, which is more
difficult to learn and thus less usable.
Reusability also interacts with your business model.
If you are in
the business of selling
software as a component. Then
you want these components to be
highly reusable so you can sell them
to a lot of customers. If
you build a component for one customer, a highly customized component, specialized for one particular
context, then you cannot
reuse it anywhere else. So the price will be higher.
What about security?
It's a very big topic,
we're not going to go very deep
into it. But it's
another aspect that is important
to consider about your software?
What kind of information does it
work with? Does it have any
sensitive data? Is it important
than only some users can do
something as opposed to others
right? We need to put some kind
of access control into it.
How available and how
reliable is the system that we
built?
Once people want
to use your software, is the
software going to be there for
them when they need it?
Or the people will have to live with the
uncertainty that when they need to
use this software now, but maybe
it's not working and I have to
come back later and hope for the
best. As architect, you have to
worry about whether you introduce a fault tolerant
design, then deploy it the right
kind of environment with enough redundancy.
This is covered under the more broad
quality of dependability.
There are many other qualities.
Sometimes you have a
problem of interfacing
a system with another one, so
how compatible is it?
How easy it is to integrate? How
portable? How much does it cost to
redeploy the system across
different platforms? How easy
it is to test my system when
I want to make sure
that is correct?
Do I have tests for it? Is it
expensive to write tests.
How easy it is to
customize my system? Does it to scale
to many users? How good is the
performance? These are the usual examples
when you think of requirements
that go beyond the correctness.
Of course, we have
a lecture on software
performance.
Still you may have the most scalable and performant system, but it is no good unless we can ship it today.
What if you need to change something, fix a bug?
How long does it take for you to
fix it and then to deliver the
fixed version to the customer?
Last but not least, how elastic
is your system?
Assume we run it in the cloud,
can it scale just enough to
handle the load and then shrink
back to the small configuration
so that it's cheaper to run?
So these are all qualities of a
software system and you as an
architect should see
yourself inside the circle with
all these arrows pointing at
you. And you need to decide
which ones are you going to
consider which one are you going
to be pushing back against.
We decide will make it really secure,
but we have to sacrifice a
little bit of usability because
people have to enter the
password or scan their faces.
We have to sacrifice a
little bit of performance because we need to encrypt the
messages.
Or we will make it
portable so that we can sell it
too many customers but it will need to
e virtualized
and will be will run a bit slower.
The message is that you cannot
have the perfect system where
every quality is maximized so
you always have to balance and
and trade off one quality against another.
One thing that
we will practice is how to do
these trade offs between
different qualities.
You can also look at this picture as a way to to
structure your path into the
topic of software architecture.
We will spend some time going
over the qualities and defining them in detail, and then we will discuss how to design architectures which can deliver each quality in a way that should
be independent from the way that
you program it.
So that's
the main idea for this lecture.
Change
Software is expected to change. Software is meant to change. The software architecture includes all the design decisions about the software which are hard to change.
If you decide to write your code in a programming language, you may not be able to afford to spend 6 months developing your system and then go back on your decision and switch to another language.
Once you make an architectural decision, you decide to invest into a technology, you decide to start moving in a certain direction, it becomes more and more difficult to switch or steer your project to follow another path later on.
Evolution
Architectural decisions: hard to change later on and that you wish you could get right early in a project
Stewart Brands, Ralph Johnson
Architectural decisions are
important because if they are difficult
to change, then you have to get them
right and you cannot make
mistakes the first time you make them.
You usually cannot change the location of a building after you started to build it. It's difficult to add more floors on an existing building unless the structure has been originally designed for the building to grow. It is easy to repaint a facade to change its color. It's more
difficult for example, to add
kitchen or add a bathroom where
the plumbing is not available. It is also possible to throw down non load bearing walls if you need a bigger room, or you want to open or close a window. And some furniture is meant to be rearranged on the fly.
When you think about your software, think about which elements are like the chairs which are easy to change and which elements are like the columns which shouldn't be touched or everything will collapse.
Why Software Architecture?
Manage complexity through abstraction
Communicate, remember and share global design decisions among the team
Visualize and represent relevant aspects (structure, behavior, deployment, …) of a software system
Understand, predict and control how the design impacts quality attributes of a system
Define a flexible foundation for the maintenance and future evolution of the system
Course Overview
Theory
Modeling exercises
Technology demos
Design workshops
Modeling exercises
Learn how to sketch, refine, communicate and defend your architecture from multiple perspectives
Describe an idea for your next software project, or represent an existing one
One model presented by each student
Technology Demos
Learn about how software architecture meets the code
Give a convincing demo of a component framework, a connector, a continuous integration tool, a deployment tool
One video for each student
Design Workshop
Learn about how to make architectural decisions
Present your alternative
Compare it with another one, argue why your team should adopt it
One design discussion for two/three students (one student per alternative)
References
Michael Keeling, Design it! From Programmer to Software Architect, Pragmatic Bookshelf, 2017
Michael T. Nygard, Release It! Design and Deploy Production-Ready Software, 2nd edition, Pragmatic Bookshelf, 2017
Richard N. Taylor, Nenad Medvidovic, Eric M. Dashofy, Software Architecture: Foundations, Theory and Practice, John-Wiley, 2009
Simon Brown, Software Architecture for Developers, LeanPub, 2015
George Fairbanks, Just Enough Software Architecture: A Risk Driven Approach, M&B 2010
Eberhardt Rechtin, Systems Architecting: Creating and Building Complex Systems, Prentice Hall 1991
Henry Petroski, Small Things Considered: Why There Is No Perfect Design, Vintage 2004
Ian Gordon, Essential Software Architecture, Springer 2004
Christopher Alexander, The Timeless Way of Building, Oxford University Press 1979
Stewart Brand, How Buildings Learn, Penguin 1987
Amy Brown and Greg Wilson (eds.) The Architecture of Open Source Applications , 2012