OSGi in the Enterprise: Agility, Modularity, and Architecture's Paradox
1. Kirk Knoernschild
Analyst, SDLC and Containers,
OSGi in the Enterprise
Languages, & Frameworks
Burton Group
Agility, Modularity, and Architecture’s Paradox
www.burtongroup.com
kknoernschild@burtongroup.com
Blog: http://apsblog.burtongroup.com JAX London & OSGi DevCon
Blog: http://techdistrict.kirkk.com
Twitter: pragkirk
February 23rd, 2010
2. OSGi in the Enterprise 2
“First they ignore you, then they
ridicule you, then they fight you,
then you win.”
-- Mahatma Gandhi
3. OSGi in the Enterprise 2
“First they ignore you, then they
ridicule you, then they fight you,
then you win.”
-- Mahatma Gandhi
OSGi is a disruptive technology that will transform how
enterprise Java applications are designed, developed,
and managed!
5. OSGi in the Enterprise 4
Complexity
Architectural Agility
Paradox
Modularity
6. OSGi in the Enterprise 4
Complexity
Architectural Agility
Paradox
Modularity
7. OSGi in the Enterprise 5
Complexity
Why i What’
s soft st
co mpl ware
so
How d
o we mo dul he role of
ex? co mpl tame arity?
exity?
8. Complexity 6
Rising Cost of Software Complexity
- 120 billion loc in 1990 Source: http://users.jyu.fi/~koskinen/smcosts.htm
- 250 billion loc in 2000
- loc doubles every 7 years
- 50% of development time spent understanding code
- 90% of software cost is maintenance & evolution
9. Complexity 6
Rising Cost of Software Complexity
- 120 billion loc in 1990 Source: http://users.jyu.fi/~koskinen/smcosts.htm
- 250 billion loc in 2000
- loc doubles every 7 years
- 50% of development time spent understanding code
- 90% of software cost is maintenance & evolution
Perspective: Not only double the
past 7 years, but more than total
amount ever written combined!
12. Complexity 8
Reason to Celebrate
Lehman’s Law: As a
system evolves, its
complexity increases
unless work is done to
maintain or reduce it.
www.lumaxart.com/
13. Complexity 9
BAUF Doesn’t Cut It
- BDU
F
- Exce an d BAUF!
s
docu m sive
en
- Resi tation!
sting
Chang
e!
We are often asked to design solutions to problems that
require knowledge we currently do not possess.
14. Complexity 9
BAUF Doesn’t Cut It
- BDU
F
- Exce an d BAUF!
s
docu m sive
en
- Resi tation!
sting
Chang
e!
We are often asked to design solutions to problems that
require knowledge we currently do not possess.
15. Complexity 10
Gall’s Law
A complex system that works is invariably found to have
evolved from a simple system that worked. A complex
system designed from scratch never works and cannot
be patched up to make it work. You have to start over,
beginning with a working simple system.
16. Complexity 11
Question
---------------------------------------------------------------
How do we manage software complexity?
Answer
---------------------------------------------------------------
Modularity
17. Complexity 12
Defining Module
Hey, it’s a JAR file!
- unit
of reu
- unit se
of co m
- unit po
of dep sition
- unit loyme
of ma nt
nagem
ent
A module system provides a runtime environment for modules
18. Complexity 13
Advantages of Modularity
- reus
e
- re du
ce co m
- ease ple
mainte xity
- incr nance
ease
exten
sibility
Umm...we can already do this with objects and services!
19. Complexity 13
Advantages of Modularity
- reus
- re du
e Increases architectural agility!
ce co m
- ease ple
mainte xity
- incr nance
ease
exten
sibility
Umm...we can already do this with objects and services!
20. Complexity 14
Module Design
Few teams are designing modular software systems today!
POLL:
Question: Response:
-----------------------------------------------------
- How many design class relationships? _____
- How many design package relationships? _____
- How many design service relationships? _____
- How many design module (JAR, Assembly) relationships? _____
21. Complexity 15
Platform Modularity
Why a
re
design n’t we
Platforms discourage modularity! ing mo
mo dul re
ar sof
tware
?
22. Complexity 16
Platform Modularity
- Dyn
am
- Mult ic deployme
ipl nt
- Enfo e versions
rce
depen
dencie
s
23. Complexity 16
Platform Modularity
- Dyn
am
- Mult ic deployme
This is the next generation application platform! ipl
- Enfo e versions
nt
rce
depen
dencie
s
24. OSGi in the Enterprise 17
Architectural Agility
What What What
is arc is is
hitect
ure? archit the goal of ag ility architectur
ecture ? al
?
25. Architectural Agility 18
What is Architecture?
• An architecture is the set of significant decisions about the
organization of a software system, the selection of the structural
elements and their interfaces by which the system is composed,
together with their behavior as specified in the collaborations
among those elements, the composition of these structural
elements and behavioral elements into progressively larger
subsystems, and the architecture style that guides this
organization -- these elements and their interfaces, their
collaborations, and their composition.
Source: Kruchten: The Rational Unified Process. Also cited in Booch, Rumbaugh, and
Jacobson: The Unified Modeling Language User Guide, Addison-Wesley, 1999
26. Architectural Agility 19
What is Architecture?
• In most successful software projects, the expert developers
working on that project have a shared understanding of the
system design. This shared understanding is called
‘architecture.’ This understanding includes how the system is
divided into components and how the components interact
through interfaces. These components are usually composed of
smaller components, but the architecture only includes the
components and interfaces that are understood by all the
developers...Architecture is about the important stuff. Whatever
that is.
Source: Fowler, Martin. IEEE Software, 2003. “Who Needs an Architect?” A quote from
Ralph Johnson on the XP mailing list.
27. Architectural Agility 20
What is Architecture?
• The fundamental organization of a system, embodied in its
components, their relationships to each other and the
environment, and the principles governing its design and
evolution.
Source: ANSI/IEEE Std 1471-2000
28. Architectural Agility 21
What is Architecture?
• A formal description of a system, or a detailed plan of the
system at component level to guide its implementation
• The structure of components, their inter-relationships, and the
principles and guidelines governing their design and evolution
over time.
Source: TOGAF - http://www.opengroup.org/architecture/togaf8-doc/arch/chap01.html
29. Architectural Agility 22
What is Architecture?
• Architecture embodies the critical design decisions that typify a
system.
• Relates to cost of change, organizational structure, structure of code,
capabilities of a system, etc.
• The significance of decisions needs to be understood and
assessed
• A heavy-weight approach is likely to reduce understanding and our ability to
assess
Source: QCON London Presentation by James Coplien & Kevlin Henney title Agile
Architecture Is not Fragile Architecture - http://www.infoq.com/presentations/Agile-
Architecture-Is-Not-Fragile-Architecture-James-Coplien-Kevlin-Henney
31. Architectural Agility 23
The Goal of Architecture
What if we were
able to reduce the
impact and
cost of change?
32. Architectural Agility 23
The Goal of Architecture
What if we were
able to reduce the
impact and
cost of change?
We n
ee d t
elimin o
ate
archit
ectur
e!
33. Architectural Agility 24
Reversibility
Rever
sible Ir reve
can b Decisi rsible
e eas o ns are n Decisi
ily ch ot ea
becau
se the ange d becau sily c ons
archit se the hange
ec expen y are d
acco m ture is abl siv to o
mo dat e to intens e or reso u
e cha ive. rce
nge.
First and foremost, we should try to make most decisions reversible, so
they can be made and then easily changed.
-- “Implementing Lean Software Development: From Concept to Cash”
34. Architectural Agility 24
Reversibility
Rever
sible Ir reve
can b Decisi rsible
e eas o ns are n Decisi
ily ch ot ea
becau
se the ange d becau sily c ons
archit se the hange
ec expen y are d
acco m ture is abl siv to o
mo dat e to intens e or reso u
e cha ive. rce
nge.
First and foremost, we should try to make most decisions reversible, so
they can be made and then easily changed.
-- “Implementing Lean Software Development: From Concept to Cash”
Irreversible Decisions should be made as late as possible!
36. OSGi in the Enterprise 26
Paradox
Ho w d How d Are w
o we o we ed
more de dream realize failure o o me d to
flexib sign of reu the ?
system le soft se?
s? ware
37. Paradox 27
Architecture Paradox
Increa
sing e
decre vo
ases s lvability
ur viva
bility
... making everything easy to change makes the entire
system very complex... - Ralph Johnson in “Who Needs an Architect”
38. Paradox 28
Tension
Maximizing reuse complicates use
39. Paradox 28
Tension
Maximizing reuse complicates use
- SOL
ID
- Desi
gn Pat
- Mo d terns
ularity
Patter
ns
- SOA
Princi
ples
40. Paradox 29
Architecture Paradox
Increa
sing e
decre vo
ases s lvability
ur viva
bility
... making everything easy to change makes the entire
system very complex... - Ralph Johnson in “Who Needs an Architect”
41. Paradox 29
Architecture Paradox
We m Increa
ust re sing e
decre vo
which cogniz
e ases s lvability
areas ur viva
system of the bility
deman
increa d the
se d co
that w mplex
ill bri ity
greate ng
r flex
ibility!
... making everything easy to change makes the entire
system very complex... - Ralph Johnson in “Who Needs an Architect”
43. OSGi in the Enterprise 31
Modularity
Ho w d How d How d
oe oe oe
help i s mo dularit help u s mo dularit help u s mo dularit
ncrea y s real y s o ver y
archit se ize re para d co me
ectura use? ox? the
l ag ilit
y?
44. Modularity 32
Flexibility Where?
Here?
Which
ar
system ea of the Here?
deman
flexib ds mo
ility? re
Here?
Here?
Here?
Here?
Here?
46. Modularity 34
Turtles & Architecture
What
do
archit es
ecture
do w it have t
h turt o
les?
Photo courtesy of: http://www.flickr.com/photos/mybloodyself/1108834349/
47. Modularity 34
Turtles & Architecture
What
do
archit es
ecture
do w it have t
h turt o
les?
“ Yo u’r
e ver y
yo ung clever
man, v ,
clever er y
”,
la dy. “ sai d the old
But it
all th ’s turt
e way les
down!
-- A B ”
rief H
of Tim istor y
e
Photo courtesy of: http://www.flickr.com/photos/mybloodyself/1108834349/
48. Modularity 35
Architecture “all the way down”
?
Reuse Release Equivalence:
Unit of reuse is the unit of release!
49. Modularity 35
Architecture “all the way down”
Reuse Release Equivalence:
Unit of reuse is the unit of release!
68. Modularity 42
Modular Architecture - Where to Now?
Infras Progra Design
tructu m m in g Para d
- Run re - The Mo del - The igm
time p frame techn
suppo latfor an d te w o r ks use d t iques
rt hel m ch o i den
enforc ps that a nolog ies create tify a
nd
e mo d llow u the ri
archit ular create s to of mo ght se
ecture mo dul dules t
. softw ar
are
69. Modularity 42
Modular Architecture - Where to Now?
Infras Progra Design
tructu m m in g Para d
- Run re - The Mo del - The igm
time p frame techn
suppo latfor an d te w o r ks use d t iques
rt hel m ch o i den
enforc ps that a nolog ies create tify a
nd
e mo d llow u the ri
archit ular create s to of mo ght se
ecture mo dul dules t
. softw ar
are
The Design Paradigm
- What’s the right granularity for a module?
- What the right weight for a module?
70. OSGi in the Enterprise 43
Additional Resources
• http://techdistrict.kirkk.com - Kirk’s blog with lots of content on
modularity.
• Modular Architecture Patterns - Book in Progress
• http://modularity.kirkk.com/
• http://www.osgi.org - OSGi HomePage
• OSGi in Practice by Neil Bartlett
• http://neilbartlett.name/blog/osgibook/
• Modular Java by Craig Walls
• OSGi and Equinox: Creating Highly Modular Java Systems by
Jeff McAffer, et. al.
• Tried to develop a modular architecture without OSGi?
• JarAnalyzer - http://code.google.com/p/jaranalyzer/
Editor's Notes
Hello, and welcome to OSGi in the Enterprise.
Dollo’s Law -> Reversibility -> Defer Commitment and other Lean Principles
There is a law, called Dollo’s Law, that states that evolution is not reversible. As an organism evolves, it cannot evolve into a state formerly realized in it’s ancestors. In other words, evolution is irreversible, and future possibilities can only unfold within the limits of the inherited design. Translated loosely, we are born, grow old, and die; eggs break; wood burns; these are things we accept and view as irreversible. Once done, they cannot be undone. Commonly, we take a similar approach to architecture. In other words, once architectural decisions are made, we feel they cannot be undone. Often times, this is not too far from the truth for two reasons primarily – first, the architecture is not able to accommodate change, second the architect is not willing to accommodate change. As we talk about agile architecture, we’ll try to keep these two themes in mind – the ability of the architecture and the willingness of the architect.
Lehman’s 2nd law - As a system evolves, it’s complexity increases unless work is done to maintain or reduce it.
There is a law, called Dollo’s Law, that states that evolution is not reversible. In other words, as an organism evolves, it cannot evolve into a state formerly realized in it’s ancestors. In other words, evolution is irreversible. Once an organism adopts a particular form, future possibilities can only unfold within the limits of the inherited design. More generally, irreversibility is when a closed system cannot be restored to a previous state without some expenditure of energy. This is because, as evolution progresses, or an irreversible process progresses, entropy increases. That is, the irreversible process itself requires energy that cannot be recovered, and a certain amount of energy is required as the system evolves. In the real world, we often think in terms of thermal efficiency - how much of the energy generated by my furnace is translated to heat that warms my house versus energy that is lost. A certain amount is lost due to dissipation or friction, and this cannot be recovered if we reverse the process. Irreversibility is a process that is one way over time. Translated loosely, we are born, grow old, and die; eggs break; wood burns; these are things we accept and view as irreversible. Once done, they cannot be undone. We accept this one way behavior as a simple truth - time has a certain direction. And this drives us to operate under the common sense conviction that by acting now, we can affect the future but obviously not the past. And so we try to act now.
This story of agile architecture steps beyond the common practices that state that “Avoid ivory tower architecture”, “Architects must write code”, “Perform just-in-time architecture”, “Architect throughout the lifecycle”, “Don’t use a heavyweight UML modeling tool”, “Communicate your architecture”, “Manage change and complexity”, “Deliver working solutions”, or “Prove your architecture early”. I’d like to think we take it a step further by exploring the goals of agile architecture, and then examine how we really realize these goals.
Reference: http://www.isepp.org/Pages/01-02%20Pages/Albert.html
What does this have to do with software architecture? Absolutely nothing...except that a good software architecture is not irreversible, and therefore, we are not required to make all architectural decisions RIGHT NOW!
But what if the system were reversible? What if we were able to apply energy from another external force to reverse the process. We see this today with refrigerators. In thermodynamics, heat always flows from hot to cold, not vice versa. But with a refrigerator, we use an alternative source of energy to reverse the affect.
Today, I’m going to talk about modularity in enterprise software development, and its important contribution in helping us design more flexible, adaptable, and reusable enterprise software. We’ve heard these promises, from other technologies that have come before, but modularity represents an important step in completing the architectural puzzle. Over the past 10 years, and especially that past three or four, the momentum behind modularity has been staggering, and we are on the verge of a disruptive transition that will transform how we think about designing enterprise software. Today, I’m going to tell you the story of why we need modularity in enterprise software development.
OSGi in the Enterprise - Agility, Modularity, and Architecture’s Paradox
Attempts to architect more flexible software often results in the opposite - brittle software fraught with complexity. Something is missing. Complexity is the beast we must tame, and modularity is part of the answer. In this keynote, we’ll examine the challenges of traditional approaches to software architecture, probe the paradox of architecture, and explore the inextricable link between structural and temporal architectural decisions. From the highest level applications and services to the code that exists in the bowels of the system, we expose the advantages of a modular architecture. Come learn new ways that large software systems can be organized to increase flexibility, reusability, adaptability, maintainability, testability, and extensibility. Come discover the importance of OSGi in the Enterprise!
Today, I’m going to tell you why!
I’m going to start by talking about the growing problem of software complexity. It’s quite astounding, actually. Then, we’ll move on into exploring architecture’s role in managing that complexity, from which emerges architecture’s paradox. It’s at this point, that we’ll delve more deeply into the role of modularity, which in conjunction with other paradigms such as OO and SOA, is going to help us overcome the paradox.
Defining Architecture - understanding the goal of architecture and the problems we face in realizing that goal
Modularity - A missing intermediary ingredient surrounding how we solve the problem that help us realize the goal.
Last two sections present some patterns and then a sample case study that applies those systems. The sample is gleaned from a real world project that’s been simplified for purposes of demonstration.
Or think of it this way...The Question...The Problem...The Answer
I’m going to start by talking about the growing problem of software complexity. It’s quite astounding, actually. Then, we’ll move on into exploring architecture’s role in managing that complexity, from which emerges architecture’s paradox. It’s at this point, that we’ll delve more deeply into the role of modularity, which in conjunction with other paradigms such as OO and SOA, is going to help us overcome the paradox.
Defining Architecture - understanding the goal of architecture and the problems we face in realizing that goal
Modularity - A missing intermediary ingredient surrounding how we solve the problem that help us realize the goal.
Last two sections present some patterns and then a sample case study that applies those systems. The sample is gleaned from a real world project that’s been simplified for purposes of demonstration.
Or think of it this way...The Question...The Problem...The Answer
I’m going to start by talking about the growing problem of software complexity. It’s quite astounding, actually. Then, we’ll move on into exploring architecture’s role in managing that complexity, from which emerges architecture’s paradox. It’s at this point, that we’ll delve more deeply into the role of modularity, which in conjunction with other paradigms such as OO and SOA, is going to help us overcome the paradox.
Defining Architecture - understanding the goal of architecture and the problems we face in realizing that goal
Modularity - A missing intermediary ingredient surrounding how we solve the problem that help us realize the goal.
Last two sections present some patterns and then a sample case study that applies those systems. The sample is gleaned from a real world project that’s been simplified for purposes of demonstration.
Or think of it this way...The Question...The Problem...The Answer
I’m going to start by talking about the growing problem of software complexity. It’s quite astounding, actually. Then, we’ll move on into exploring architecture’s role in managing that complexity, from which emerges architecture’s paradox. It’s at this point, that we’ll delve more deeply into the role of modularity, which in conjunction with other paradigms such as OO and SOA, is going to help us overcome the paradox.
Defining Architecture - understanding the goal of architecture and the problems we face in realizing that goal
Modularity - A missing intermediary ingredient surrounding how we solve the problem that help us realize the goal.
Last two sections present some patterns and then a sample case study that applies those systems. The sample is gleaned from a real world project that’s been simplified for purposes of demonstration.
Or think of it this way...The Question...The Problem...The Answer
Modularity - A missing intermediary ingredient surrounding how we solve the problem that help us realize the goal.
Certainly this doesn’t factor density. Dynamic languages will produce less code. But Cobol is about the same as C. http://www.embedded.com/design/210602856
Larger systems are more difficult to understand and maintain.
Writing new software impedes time-to-market. Wouldn’t it be nice to just assemble software?
Can dynamic languages help? Possibly. But they’ll grow in size too.
Certainly this doesn’t factor density. Dynamic languages will produce less code. But Cobol is about the same as C. http://www.embedded.com/design/210602856
Larger systems are more difficult to understand and maintain.
Writing new software impedes time-to-market. Wouldn’t it be nice to just assemble software?
Can dynamic languages help? Possibly. But they’ll grow in size too.
FreeBSD - 2002 at roughly 8 million. 2009 not quite at 16 million.
Linux Kernel - 2004 at 6 million. 2009 at 12 million.
Software growth is a good thing. It means people are using your system and are demanding more from it. They like it and they want to keep using it. Software that
- doesn’t evolve dies and
- cannot evolve dies.
If a software system doubles in size every 7 years, it’s doubtful the original architecture was able to predict all that is yet to come. BAUF cannot predict the architectural shifts that will occur.
Architects architect architecture - social process structure
delineate architecture from design
BAUF cannot work
evolution is critical.
A few preliminary notes before we get started….
Isn’t it amazing that we often try to define a system’s architecture before we have a solid understanding of the business requirements that the architecture must support? Often, we attempt to design a flexible architecture, but fail to design flexibility in the necessary areas.
And what of this? What actually is the difference between architecture and design? Certainly complexity has something to do with this. But complexity can easily derail. And as Gall’s law states…
Again, keep these ideas in mind as we progress throughout the presentation.
BAUF/BDUF cannot work. We design flexibility where is isn’t needed. We cannot predict. Tell story of Java EE patterns (DAO factory to switch db, but not deal with different datastores).
A runtime environment isn’t enough, though. We also need tools that help with the prog. model and well as knowledge surrounding the design paradigm. EJB or OO example from blog.
Enterprise Java Beans (EJB), and especially entity beans, were presented as part of Java EE as a way to componentize business applications. The runtime capabilities of EJB were very alluring - transactions, persistence, security, transparency, etc. - and baked directly into the platform. Unfortunately, there were two glaring problems. The development model was complex and it was not well understood.
It was a number of years ago, but I recall vividly my first experience with EJB. I arrived on the team mid-way through their development effort. At that point, they had more than 100 entity beans, the localhost environment took more than four hours to start-up, and problems were rampant. I stuck around for three weeks before I got the hell out. The project wound up getting cancelled. Developers were able to easily understand the EJB programming model (especially with all the code generation wizards), but lacked the design wisdom to use EJB effectively.
Another tool in our toolbox that help with architecture. Object are too fine grained. Services too coarse. Modularity just right.
While few teams are designing modular software systems, they should be. The goal of architecture necessitates it. So what is this goal of architecture.
Now we’ll explain how modularity increases architectural agility by allowing us to realize these benefits. First, I want to level set on the goal of architecture.
Pretty good reason why we don’t design this way.
What if the platform did support modularity?
As platform support for modularity increases, more teams will want to take advantage of the benefits of modularity. And like we’ve so often seen in the past, teams will struggle to realize these benefits. To understand why, I want to back up, start at the beginning, and talk about software architecture.
Software growth is a good thing. It means our software is surviving. As software grows, its architecture must evolve. Evolution is imperative, implying that we must have an architecture that can adapt. Without it, our systems will die. So how do we create this type of agile architecture? First, let’s look at architecture and examine what it takes to create this type of adaptive architecture.
What do we try to accomplish with architecture? What is it’s goal?
Summary of key phrases -> Components, Significant Decisions, Shared Understanding, Relationships and organization of the system, evolution.
Without question, architectural shifts will occur throughout the course of the project. Sometimes, we anticipate correctly. Sometimes not. Agile architecture is defined by our willingness and ability to embrace architectural change. Yet to embrace architectural change demands that we have an architecture that can accommodate change. Simply because a process is employed that embraces architectural change throughout the software lifecycle does not mean that it’s possible to make that change. Here, the inextricable link between the temporal and structural aspect is established.
Whereas the temporal aspect of agile architecture demands that the architect be flexible, the structural aspect of agile architecture demands that the architecture be flexible so that the team is able to quickly make the change. Agile architecture demands both, and the absence of one precludes the presence of the other.
Modularity is a key ingredient of agile architecture. Modularity ensures that development teams understand architectural dependencies that are going to inhibit or accommodate change. Simply embracing an attitude of change is not enough. We must also be able to accommodate change efficiently. Modularity allows the development team to envision and manage change more easily, meaning they’ll be able to make the change they want to make when they want to make it.
So what makes something significant enough to be deemed architectural? Difficult to change. Why hard to change? Don’t understand, complex, lacks flexibility. Irreversibility. What if we could make them reversible?
The underlying goal of agile architecture is to defer commitment for decisions until we have the knowledge we need to make the decision. At least, this is the case for the irreversible decisions. For reversible decisions, it doesn’t matter because the decision can be changed at any time. Making decisions reversible is the essence of agile architecture.
Well...actually...we need to minimize the impact and cost of change, thereby making change less architecturally significant.
The analogy we draw comparing building and software architecture is flawed. Changing a building is difficult. Adding a new floor in between the 2nd and 3rd floor of a building is always incredibly expensive. However, software can be made easy to change, and the software architecture should strive to make this a goal.
In fact, there is no absolute or theoretical reason that anything is hard to change about software. If you pick any one aspect of software then you can make it easy to change, but we don’t know how to make everything easy to change. And making something easy to change inevitably makes the overall system more complex. And making everything easy to change makes the entire system very complex. Complexity is what makes software hard to change. Software is not limited by physics like buildings and bridges are. It is limited only by imagination, design. In other words, it is limited by our abilities, not the properties of the real world. The enemy of software is us.
Yet, the way we minimize the impact and cost of change presents a challenging paradox.
So what makes something significant enough to be deemed architectural? Difficult to change. Why hard to change? Don’t understand, complex, lacks flexibility. Irreversibility. What if we could make them reversible?
The underlying goal of agile architecture is to defer commitment for decisions until we have the knowledge we need to make the decision. At least, this is the case for the irreversible decisions. For reversible decisions, it doesn’t matter because the decision can be changed at any time. Making decisions reversible is the essence of agile architecture.
Well...actually...we need to minimize the impact and cost of change, thereby making change less architecturally significant.
The analogy we draw comparing building and software architecture is flawed. Changing a building is difficult. Adding a new floor in between the 2nd and 3rd floor of a building is always incredibly expensive. However, software can be made easy to change, and the software architecture should strive to make this a goal.
In fact, there is no absolute or theoretical reason that anything is hard to change about software. If you pick any one aspect of software then you can make it easy to change, but we don’t know how to make everything easy to change. And making something easy to change inevitably makes the overall system more complex. And making everything easy to change makes the entire system very complex. Complexity is what makes software hard to change. Software is not limited by physics like buildings and bridges are. It is limited only by imagination, design. In other words, it is limited by our abilities, not the properties of the real world. The enemy of software is us.
Yet, the way we minimize the impact and cost of change presents a challenging paradox.
So what makes something significant enough to be deemed architectural? Difficult to change. Why hard to change? Don’t understand, complex, lacks flexibility. Irreversibility. What if we could make them reversible?
The underlying goal of agile architecture is to defer commitment for decisions until we have the knowledge we need to make the decision. At least, this is the case for the irreversible decisions. For reversible decisions, it doesn’t matter because the decision can be changed at any time. Making decisions reversible is the essence of agile architecture.
Well...actually...we need to minimize the impact and cost of change, thereby making change less architecturally significant.
The analogy we draw comparing building and software architecture is flawed. Changing a building is difficult. Adding a new floor in between the 2nd and 3rd floor of a building is always incredibly expensive. However, software can be made easy to change, and the software architecture should strive to make this a goal.
In fact, there is no absolute or theoretical reason that anything is hard to change about software. If you pick any one aspect of software then you can make it easy to change, but we don’t know how to make everything easy to change. And making something easy to change inevitably makes the overall system more complex. And making everything easy to change makes the entire system very complex. Complexity is what makes software hard to change. Software is not limited by physics like buildings and bridges are. It is limited only by imagination, design. In other words, it is limited by our abilities, not the properties of the real world. The enemy of software is us.
Yet, the way we minimize the impact and cost of change presents a challenging paradox.
So what makes something significant enough to be deemed architectural? Difficult to change. Why hard to change? Don’t understand, complex, lacks flexibility. Irreversibility. What if we could make them reversible?
The underlying goal of agile architecture is to defer commitment for decisions until we have the knowledge we need to make the decision. At least, this is the case for the irreversible decisions. For reversible decisions, it doesn’t matter because the decision can be changed at any time. Making decisions reversible is the essence of agile architecture.
Well...actually...we need to minimize the impact and cost of change, thereby making change less architecturally significant.
The analogy we draw comparing building and software architecture is flawed. Changing a building is difficult. Adding a new floor in between the 2nd and 3rd floor of a building is always incredibly expensive. However, software can be made easy to change, and the software architecture should strive to make this a goal.
In fact, there is no absolute or theoretical reason that anything is hard to change about software. If you pick any one aspect of software then you can make it easy to change, but we don’t know how to make everything easy to change. And making something easy to change inevitably makes the overall system more complex. And making everything easy to change makes the entire system very complex. Complexity is what makes software hard to change. Software is not limited by physics like buildings and bridges are. It is limited only by imagination, design. In other words, it is limited by our abilities, not the properties of the real world. The enemy of software is us.
Yet, the way we minimize the impact and cost of change presents a challenging paradox.
How do we make decisions reversible? We try to design flexible software that can adapt to change. Herein lies the paradox.
We try to reduce the impact and cost of change by designing more flexible systems. How do we design more flexible software systems? Attempt to accommodate variances in behavior given a particular context using a variety of techniques (external configuration, DI, reflection, OO). But this flexibility naturally increases complexity, and herein lies a problem. We attempt to create lightweight cohesive entities at the right level of granularity. They don’t do too much, yet do enough to make them useful - easy to understand, use, and change. But we continue to struggle.
We design flexible systems to the point where we can’t understand it. Massive object models (layers, DI, reflection, etc.). Lots of external configuration. We need something else beyond objects. We must recognize where flexibility is needed. WE NEED MODULARITY.
Once we’ve got this flexible system, with layers, dependency injection, external configurations, reflection, lots of extensibility, we discover that noone can understand it. And as the system grows, the problem is only exacerbated.
A system survives as long as it can evolve. To survive, the architecture must be flexible. Unfortunately, because flexibility increases complexity, the impact and cost of change also increases. And with each change, entropy sets in which further decreases evolvability and survivability.
There is a tension that exists between granularity and weight that makes our entities more reusable, though less useable or more useable, yet less useable. ...
Weight - Dependency on the environment. Granularity - extent to which system is broken into parts. There is tension here. Ex. Should a module pay the bill (dup check, audit, pay, remit) or should each be a separate module?
It also makes the system more difficult to maintain and increases complexity (remember the paradox).
Granularity
Granularity is the extent to which a system is broken down into parts. Coarse-grained components tend to be richer in behavior than fine-grained components. Because coarse-grained components do more, they tend to be bigger than fine-grained components. To maximize reuse, we try composing coarse-grained components from fine-grained components. Of course, this results in a lot of dependencies between components, making them more difficult to use. In general, we can say the following:
Coarse-grained components are easier to use, but fine-grained components are more reusable.
Time for an example. Let’s say we’re creating a component that processes health insurance claims. Let’s keep the business process relatively simple here to maintain our sanity. There are four steps in the process. First, the system is fed the claim information. Second, the system checks to make sure it’s not a duplicate submission. Third, the system reprices the claim based on HMO and PPO agreements. Fourth, the system remits payment. A coarse-grained component would perform all four of these steps.
In doing this, we’ve made it easy to use since we only need to invoke one operation to complete the whole process. But it’s also more difficult to reuse only a portion of this process, such as the remit payment code. The logical solution is to create four fine-grained components (one for each step in the process) and one coarse-grained component composed of the four others that pulls everything together. The fine-grained components make things more reusable, but are also more difficult to use since we have to do more to pull them all together to perform a unit of work.
Weight
Weight is the extent to which a component depends on it’s environment. A heavyweight component depends on it’s operating environment, while a lightweight component avoids these dependencies. When creating a component that runs in multiple environments, we’re forced to move the environment specific dependencies (ie. context dependencies) from code to configuration. This makes the component more reusable, but it’s also a bit more difficult to use since the component must be configured for each environment.
Designing and configuring a lightweight component is more difficult than simply dropping in a component programmed to operate in that environment. In general, we can say the following:
Lightweight components are more reusable, but heavyweight components are easier to use.
Let’s elaborate using the example above, where the solution was to create one coarse-grained component composed of four fine-grained components. If each of these components only needs to run within a single application in a single operating environment, we can encapsulate all of this environmental code into each component, making each heavyweight. But if we want to reuse these components across applications and operating environments, then we have to move this code outside of the component and ensure it can be configured for each environment in which we want it to operate.
There is a tension that exists between granularity and weight that makes our entities more reusable, though less useable or more useable, yet less useable. ...
Weight - Dependency on the environment. Granularity - extent to which system is broken into parts. There is tension here. Ex. Should a module pay the bill (dup check, audit, pay, remit) or should each be a separate module?
It also makes the system more difficult to maintain and increases complexity (remember the paradox).
Granularity
Granularity is the extent to which a system is broken down into parts. Coarse-grained components tend to be richer in behavior than fine-grained components. Because coarse-grained components do more, they tend to be bigger than fine-grained components. To maximize reuse, we try composing coarse-grained components from fine-grained components. Of course, this results in a lot of dependencies between components, making them more difficult to use. In general, we can say the following:
Coarse-grained components are easier to use, but fine-grained components are more reusable.
Time for an example. Let’s say we’re creating a component that processes health insurance claims. Let’s keep the business process relatively simple here to maintain our sanity. There are four steps in the process. First, the system is fed the claim information. Second, the system checks to make sure it’s not a duplicate submission. Third, the system reprices the claim based on HMO and PPO agreements. Fourth, the system remits payment. A coarse-grained component would perform all four of these steps.
In doing this, we’ve made it easy to use since we only need to invoke one operation to complete the whole process. But it’s also more difficult to reuse only a portion of this process, such as the remit payment code. The logical solution is to create four fine-grained components (one for each step in the process) and one coarse-grained component composed of the four others that pulls everything together. The fine-grained components make things more reusable, but are also more difficult to use since we have to do more to pull them all together to perform a unit of work.
Weight
Weight is the extent to which a component depends on it’s environment. A heavyweight component depends on it’s operating environment, while a lightweight component avoids these dependencies. When creating a component that runs in multiple environments, we’re forced to move the environment specific dependencies (ie. context dependencies) from code to configuration. This makes the component more reusable, but it’s also a bit more difficult to use since the component must be configured for each environment.
Designing and configuring a lightweight component is more difficult than simply dropping in a component programmed to operate in that environment. In general, we can say the following:
Lightweight components are more reusable, but heavyweight components are easier to use.
Let’s elaborate using the example above, where the solution was to create one coarse-grained component composed of four fine-grained components. If each of these components only needs to run within a single application in a single operating environment, we can encapsulate all of this environmental code into each component, making each heavyweight. But if we want to reuse these components across applications and operating environments, then we have to move this code outside of the component and ensure it can be configured for each environment in which we want it to operate.
There is a tension that exists between granularity and weight that makes our entities more reusable, though less useable or more useable, yet less useable. ...
Weight - Dependency on the environment. Granularity - extent to which system is broken into parts. There is tension here. Ex. Should a module pay the bill (dup check, audit, pay, remit) or should each be a separate module?
It also makes the system more difficult to maintain and increases complexity (remember the paradox).
Granularity
Granularity is the extent to which a system is broken down into parts. Coarse-grained components tend to be richer in behavior than fine-grained components. Because coarse-grained components do more, they tend to be bigger than fine-grained components. To maximize reuse, we try composing coarse-grained components from fine-grained components. Of course, this results in a lot of dependencies between components, making them more difficult to use. In general, we can say the following:
Coarse-grained components are easier to use, but fine-grained components are more reusable.
Time for an example. Let’s say we’re creating a component that processes health insurance claims. Let’s keep the business process relatively simple here to maintain our sanity. There are four steps in the process. First, the system is fed the claim information. Second, the system checks to make sure it’s not a duplicate submission. Third, the system reprices the claim based on HMO and PPO agreements. Fourth, the system remits payment. A coarse-grained component would perform all four of these steps.
In doing this, we’ve made it easy to use since we only need to invoke one operation to complete the whole process. But it’s also more difficult to reuse only a portion of this process, such as the remit payment code. The logical solution is to create four fine-grained components (one for each step in the process) and one coarse-grained component composed of the four others that pulls everything together. The fine-grained components make things more reusable, but are also more difficult to use since we have to do more to pull them all together to perform a unit of work.
Weight
Weight is the extent to which a component depends on it’s environment. A heavyweight component depends on it’s operating environment, while a lightweight component avoids these dependencies. When creating a component that runs in multiple environments, we’re forced to move the environment specific dependencies (ie. context dependencies) from code to configuration. This makes the component more reusable, but it’s also a bit more difficult to use since the component must be configured for each environment.
Designing and configuring a lightweight component is more difficult than simply dropping in a component programmed to operate in that environment. In general, we can say the following:
Lightweight components are more reusable, but heavyweight components are easier to use.
Let’s elaborate using the example above, where the solution was to create one coarse-grained component composed of four fine-grained components. If each of these components only needs to run within a single application in a single operating environment, we can encapsulate all of this environmental code into each component, making each heavyweight. But if we want to reuse these components across applications and operating environments, then we have to move this code outside of the component and ensure it can be configured for each environment in which we want it to operate.
and we have to be careful in managing complexity by understanding where the complexity is warranted. Sadly, we cannot always do this because of unanticipated change. We have to do our best, by working to accommodate change that causes architecture to shift.
We try to reduce the impact and cost of change by designing more flexible systems. But flexibility naturally increases complexity, and we have to be careful in managing complexity by understanding where the complexity is warranted. Sadly, we cannot always do this because of unanticipated change. We have to do our best, by working to accommodate change that causes architecture to shift.
How do we design more flexible software systems? Small cohesive entities at the right level of granularity. They don’t do too much, yet do enough to make them useful. Attempt to accommodate variances in behavior given a particular context using a variety of techniques (external configuration, DI, reflection, OO). Herein lies a problem. There is a tension that exists between granularity and weight that makes our entities more reusable, though less useable or more useable, yet less useable. ...
We design flexible systems to the point where we can’t understand it. Massive object models (layers, DI, reflection, etc.). Lots of external configuration. We need something else beyond objects. We must recognize where flexibility is needed. WE NEED MODULARITY.
Once we’ve got this flexible system, with layers, dependency injection, external configurations, reflection, lots of extensibility, we discover that noone can understand it. And as the system grows, the problem is only exacerbated.
A system survives as long as it can evolve. To survive, the architecture must be flexible. Unfortunately, because flexibility increases complexity, the impact and cost of change also increases. And with each change, entropy sets in which further decreases evolvability and survivability.
and we have to be careful in managing complexity by understanding where the complexity is warranted. Sadly, we cannot always do this because of unanticipated change. We have to do our best, by working to accommodate change that causes architecture to shift.
We try to reduce the impact and cost of change by designing more flexible systems. But flexibility naturally increases complexity, and we have to be careful in managing complexity by understanding where the complexity is warranted. Sadly, we cannot always do this because of unanticipated change. We have to do our best, by working to accommodate change that causes architecture to shift.
How do we design more flexible software systems? Small cohesive entities at the right level of granularity. They don’t do too much, yet do enough to make them useful. Attempt to accommodate variances in behavior given a particular context using a variety of techniques (external configuration, DI, reflection, OO). Herein lies a problem. There is a tension that exists between granularity and weight that makes our entities more reusable, though less useable or more useable, yet less useable. ...
We design flexible systems to the point where we can’t understand it. Massive object models (layers, DI, reflection, etc.). Lots of external configuration. We need something else beyond objects. We must recognize where flexibility is needed. WE NEED MODULARITY.
Once we’ve got this flexible system, with layers, dependency injection, external configurations, reflection, lots of extensibility, we discover that noone can understand it. And as the system grows, the problem is only exacerbated.
A system survives as long as it can evolve. To survive, the architecture must be flexible. Unfortunately, because flexibility increases complexity, the impact and cost of change also increases. And with each change, entropy sets in which further decreases evolvability and survivability.
What do we try to accomplish with architecture? What is its goal?
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
Architecture all the way down expands our options. It expands our deployment options. It expands our ability to compose new functionality from existing functionality. It expands our reuse options. So here’s an example.
Every major software technology trend of the past two decades cites reuse as a benefit. OO & services are two really good examples. Objects are really fine-grained entities, and compared to objects, services are relatively coarse-grained. So a big problem with reuse is finding something that’s at the right level of granularity for me to use. If a service does too much, I can’t reuse it. And once that happens, I’m forced to look at the objects, which are really hard to understand because there’s nothing bridging services and objects. But with modules, I have that intermediate unit. If a service doesn’t give me what I want, I can look to the finer-grained modules to assemble a new unit that does give me what I want.
BillPay example - pay a bill --> check for dups, audit, pay, remit (service, module, package, or class).
"A well-known scientist (some say it was Bertrand Russell) once gave a public lecture on astronomy. He described how the earth orbits around the sun and how the sun, in turn, orbits around the center of a vast collection of stars called our galaxy. At the end of the lecture, a little old lady at the back of the room got up and said: "What you have told us is rubbish. The world is really a flat plate supported on the back of a giant tortoise." The scientist gave a superior smile before replying, "What is the tortoise standing on?" "You're very clever, young man, very clever", said the old lady. "But it's turtles all the way down!"
- A Brief History of Time by Stephen Hawking
"A well-known scientist (some say it was Bertrand Russell) once gave a public lecture on astronomy. He described how the earth orbits around the sun and how the sun, in turn, orbits around the center of a vast collection of stars called our galaxy. At the end of the lecture, a little old lady at the back of the room got up and said: "What you have told us is rubbish. The world is really a flat plate supported on the back of a giant tortoise." The scientist gave a superior smile before replying, "What is the tortoise standing on?" "You're very clever, young man, very clever", said the old lady. "But it's turtles all the way down!"
- A Brief History of Time by Stephen Hawking
Architecture all the way down expands our options. It expands our deployment options. It expands our ability to compose new functionality from existing functionality. It expands our reuse options. So here’s an example.
Every major software technology trend of the past two decades cites reuse as a benefit. OO & services are two really good examples. Objects are really fine-grained entities, and compared to objects, services are relatively coarse-grained. So a big problem with reuse is finding something that’s at the right level of granularity for me to use. If a service does too much, I can’t reuse it. And once that happens, I’m forced to look at the objects, which are really hard to understand because there’s nothing bridging services and objects. But with modules, I have that intermediate unit. If a service doesn’t give me what I want, I can look to the finer-grained modules to assemble a new unit that does give me what I want.
BillPay example - pay a bill --> check for dups, audit, pay, remit (service, module, package, or class).
Architecture all the way down expands our options. It expands our deployment options. It expands our ability to compose new functionality from existing functionality. It expands our reuse options. So here’s an example.
Every major software technology trend of the past two decades cites reuse as a benefit. OO & services are two really good examples. Objects are really fine-grained entities, and compared to objects, services are relatively coarse-grained. So a big problem with reuse is finding something that’s at the right level of granularity for me to use. If a service does too much, I can’t reuse it. And once that happens, I’m forced to look at the objects, which are really hard to understand because there’s nothing bridging services and objects. But with modules, I have that intermediate unit. If a service doesn’t give me what I want, I can look to the finer-grained modules to assemble a new unit that does give me what I want.
BillPay example - pay a bill --> check for dups, audit, pay, remit (service, module, package, or class).
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
How does modularity affect how we design? Joints of the system are more architecturally significant. With more flexible joints, we can accommodate shifts.
Maximize flexibility by emphasizing the joints within the system.
Just like TDD drives how we design our classes, modularity drives how we allocated classes to their deployment units.
Barbara Liskov OOPSLA 2010 - “It’s more important to make programs easier to read than to write.” In other words, we have to increase understanding. This helps reduce the impact and cost of change.
Barbara Liskov OOPSLA 2010 - “It’s more important to make programs easier to read than to write.” In other words, we have to increase understanding. This helps reduce the impact and cost of change.
Barbara Liskov OOPSLA 2010 - “It’s more important to make programs easier to read than to write.” In other words, we have to increase understanding. This helps reduce the impact and cost of change.
Barbara Liskov OOPSLA 2010 - “It’s more important to make programs easier to read than to write.” In other words, we have to increase understanding. This helps reduce the impact and cost of change.
Barbara Liskov OOPSLA 2010 - “It’s more important to make programs easier to read than to write.” In other words, we have to increase understanding. This helps reduce the impact and cost of change.
Barbara Liskov OOPSLA 2010 - “It’s more important to make programs easier to read than to write.” In other words, we have to increase understanding. This helps reduce the impact and cost of change.
Barbara Liskov OOPSLA 2010 - “It’s more important to make programs easier to read than to write.” In other words, we have to increase understanding. This helps reduce the impact and cost of change.