Abstract
The idea of this talk is to help development teams to make correct architectural decisions.
Andrei will highlight the basic architectural principles and show ways to achieve architecture that is good enough to cover the project requirements and evolve in the future.
He will also present several cases from real projects, where wrong, missing, or over-sophisticated architecture decisions really hurt the development teams:
- Painful sharing: do shared modules increase reusability or will be the source of problems?
- Microservices are the solution to every problem!
- Non-extensible extensibility: too sophisticated configuration hurts
- Over fine-grained: incorrect splitting to Microservices can make life even harder as with monolith
- Convey horizontal split: how organizational driven split can jeopardise the architecture
- Model-driven: central responsibility blocks and limits the team
- Cargo cult: blindly following patterns and rule can produce an unmaintainable system
- Freestyle architecture: what happens if teams completely ignore architecture
- Improve with less intelligence: smart endpoint and dumb pipes
2. Agenda
● Architector role and Architecture definitions
● Cases, when architecture decisions hurt team (*)
○ Context
○ Observations (what happens)
○ Solution and lesson learned
○ Discussion
● Conclusion
* Examples was taken from VMWare Tanzu Labs, TYMIQ GmbH and INNOQ projects
3. About Me
- Software Engineer at VMWare Tanzu Labs
- Committer in Spring and Apache projects
- Co-founder Tymiq GmbH
- Speaker at technical conferences
4. Architecture Definitions
⟨system⟩ fundamental concepts or
properties of a system in its
environment embodied in its
elements, relationships, and in the
principles of its design and evolution
(ISO 42010)
Architecture represents the significant
design decisions that shape a system,
where significant is measured by cost
of change." -- Grady Booch.
Architecture is anything that team
considers important enough for
the system development and
evolving
5. Architecture is NOT:
Upfront activity performed by somebody in charge of telling
everyone else what to do
It is not a description or a document, it is a property of your
system or even: it is your system (intentional or accidental)
12. Online Shop Design
Customer Domain Article Domain Order Domain
User Service Cart Service Article Service Order Service
SAP
Messaging
REST REST REST REST
Core Domain
DAOs
DB DB DB
SAP Connector Messaging Connector
13. • Modification and maintenance of common domains
is hard
• Deployment in single container causes dependencies
and fragility between teams
• Migrations to new versions of Java, Hibernate, CXF
are extremely difficult and took very long time
Observation
14. Step 1: Split Codebase due Domain Code Duplication
User Customer
Domain
Checkout
Article Domain
Order Domain
User Service Cart Service Checkout Service Order Service
SAP
Messaging
REST REST REST REST
User Core
Domain
DAOs
DB
Container
Cart Customer
Domain
Cart Core
Domain
Core Order
Domain
Cart Article
Domain
Checkout Core
Domain
Core
framework as
thridparty
15. 15
Step 2: Extract Services with High Availability Requirements
Gateway
Old Service2
inside Monolith
Price&Availability
Microservice
Monolith container
Consumer 1 Consumer 2 Consumer 3
Routing / Canary release
90% 10%
Old Service1
inside Monolith
Old Service3
inside Mnolith
• Service belongs to different
bounded context and has multiple
rates of change
• Request load is essentially higher
(or lower) as rest monolith
components
• Service has independent lifecycle
• Service isolates external system
dependency
• Service uses innovative
technology
16. Step 3: Decentralize Data Management
Docker
Order Service
REST
R
E
S
T
Docker
Checkout
Service
REST
R
E
S
T
Docker
Cart Service
REST
R
E
S
T
Docker
User Service
REST
R
E
S
T
SAP
Messaging
DB
DB
DB DB
17. • Think twice before share module, especially across bounded
contexts
• Duplication is less critical as common dependencies
• Common utils can be treated as third party libraries and
make them as thin as possible
• Making decisions, system evolving and maintenance inside
team is a lot of easier as a cross teams
• Clear teams responsibility is important
Lessons Learned
19. Context
• E-Commerce (retail) provider
• Global customer base
• Platform for the clients that served their clients
• Catalog/CMS/Shop/Fulfilment
• Multi-tenant
• Highly customizable
21. • If you attempt to satisfy everyone, you will likely end up
to satisfying no one
• Specific solution is often more preferable as highly
configurable one
• Complex configuration often evolves to discovering own
programming language
Lessons Learned
25. • Legacy technology
• Code difficult to support and maintain
• Hard to extend for new payment providers
Problems reported by customer
26. • Split to microservices to make code maintainable
• Microservices architecture will help to make architecture
more extensible
Initial plan from customer
27. • There is only single bounded context
• Both modules service and job belong to this bounded
context
• There is single business domain model
• Splitting to other modules / microservices doesn’t make
sense at all and can make problems even worse
Analyse shows
28. • Service and Job were rewritten using TDD and pair
programming
• Both modules were migrated to SpringBoot, Spring Batch was
used for Job to get monitoring out of the box
• Huge amount of optimizations were done
• Both modules shared the same database and data model
Final Solution
29. • Unnecessary splitting of modules belonging in the same
bounded context can cause more problems in
architecture
• Microservices is not universal solution and wouldn’t
improved bad design automatically
• The main reasons of splitting are: business subdomain,
scalability requirements, lifecycle, failure isolation,
different technology stack
Lessons Learned
40. • Any feature requires communication between the teams
• One group should wait for another one
• If backend systems are unresponsive, frontend teams
quickly becomes secret „full stack“
54. Lessons learned
• Small is not always beatifull
• Not what is popular is automatically useful (CDD, HDD)
• Don’t copy somebody else architecture unless you sure
your context is identical
57. Symtpoms
• Ritual inclusion of code or program structures that serve no
real purpose (redundant checks for null values, testing
whether a collection is empty before iterating )
• Copying existing code with little understanding of how it
works
• Applying a design pattern or coding style blindly without
understanding the reasons behind that design principle
• Trying to make system too flexible: adopting different types
of databases, configuration sources, communication
protocols even if they do not really needed
58. Context
• Framework to discover, configure and secure web
services
• Customer is flight modelling company
• 10 developers
59. Design
Database
Repository Layer
Model Layer
Configuration
Layer
API Layer
Configuration technical
service
Repository
Repository Layer
Wiring Layer
Artifact Layer
API Layer
Service Registry
SQL, Non-SQL DBs
Impl 2, 3
File, DB, Git
Other repos
Other wirings
Impl 2, 3
Mapping
Mapping
Mapping
Mapping
Mapping
Mapping
… …
Communication
abstraction
Communication
abstraction
http://
Queue
60. Lessons learned
• Abstractions in system design are often leaky
• Build new layers carefully: not because of fashion, coolness or
dreams
• Be pragmatic for now, but predict system evolving
• Upfront architecture often leads to over-engineering
73. But …
• Luck of standartization led to ineffecient UI integration at
runtime (integration was done at hock)
• Vast differences in API style, formats, documentation created
needless extra work (json+hal, json+saron)
74. You cannot decide to not have an architecture; if you don‘t
actively create it, be prepare to deal with the one what emerges
There is a fine line between diversity (that adds value) and chaos
(that doesn‘t)
Extremely loose coupling requires a few rules, but they need to
be enforced strictly
75. Takeaways
• Don‘t be afraid about architecture
• Choose the simplest thing that will work
• Create evolvable structures, manage architecural evolution
• Don‘t built road blocks, create value and get out of the way
76. 76
Sharing Modules and Services
Team A
Module A
Team B
API
Module A
API
Module B
Team A
Service A
Team B
API
Service B
API
77. 77
Sharing Modules and Services
Team A
Module A
Team B
API
Module A
API
Module B
Team A
Service A
Team B
API
Service B
API