Scaling App development at Zalando
如果无法正常显示,请先停止浏览器的去广告插件。
相关话题:
#zalando
1. Scaling App development at
Zalando
Alexey Agapitov & Volker Leck
2. Agenda
1. Intro
2. Business challenges and development evolution
3. Drivers for modularization
4. Principles of modular architecture
5. Catalog case-study
6. Challenges & learnings
3. About Zalando
● Online fashion retail company with ~16000 employees from 140 countries
● Offices in Berlin, Dortmund, Dublin, Helsinki
● Active in 23 countries in Europe
● 45 Million active customers in Q2 2021
● 4500 brands
● As of October 2021: listed in the German Stock Market Index (DAX)
4. Teams structure
●
6 Pillars
○
●
6 Programs
○
●
Own screens and bigger
features
Contribute to different user
journeys
4 platform teams
Innersourcing is at the core of
this model.
5. Committers per year
6. Why modularize?
● Increasing complexity and cognitive load
● Unclear ownership and review process
● Increasing number of conflicts at coupling points
● Increasing build times
7. Wanted Qualities
● Supports parallel development
● Easy to contribute
● Clear code ownership model
● Highly configurable
● Easy to test
● Short feedback cycles, fast builds
8. Locality and Proximity
● Codebase is easy to explore
● Domain concepts at the top levels
● Sub-systems identifiable via folder
structure
Related concepts in close
proximity
●
├── ...
└── features
├── home
├── categorytree
└── catalog
├── brand
├── campaign
├── product
└── …
├── pdp
├── checkout
├── outfits
└── ...
9. Low coupling
Change is usually local to a module. It does not affect other modules.
10. High Cohesion
Keep together what changes at the same time and for the same reasons.
Keep apart what changes at different times and for different reasons.
11. Changes at leaf modules
unstable
stable
Leaf 1
Leaf 2
core
Leaf 3
12. Changes at leaf modules - Example Router
A router needs to know all the targets to navigate to.
router
Screen A
Screen B
Screen C
...
13. Changes at leaf modules - Example Router
A router needs to know all the targets to navigate to, but only at runtime.
Screen A Screen B Screen C
(provides Handler) (provides Handler) (provides Handler)
Extensible router
(defines Handler interface,
accepts implementations)
...
14. Plugin Architecture
API
Extensible
Feature
API
Extensible
CORE
(stable)
Feature
API
...
...
API
API
Extensible
Feature
FEATURES
(unstable)
15. Zooming in
● Same principles apply within a feature
● Stable parts vs fluently changing areas of experimentation/development
● Extract stable and extensible core machinery
● Changing contributions plug into core
● Enables rapid experimentation and Premise contributions
16. Case Study: Catalog
17. Case Study: Catalog
Core engine (extensible)
● Provides data from Backend
● Defines contract for extensions
● Triggers Parsing/Rendering of content
Extensions
● Implement contract
● Register with core
● Render concrete catalog items
18. Case Study: Catalog - Parsing contract
interface CatalogItem {
interface Dispatcher {
fun parserFor(node: CatalogNode): Parser?
}
interface Parser {
fun parse(node: CatalogNode): CatalogItem?
}
fun isFullWidthItem(): Boolean = false
...
}
19. Case Study: Catalog - Rendering contract
abstract class CatalogItemWidget(val itemView: View) {
abstract fun bind(item: CatalogItem)
...
interface Factory {
fun withParent(parent: ViewGroup): CatalogItemWidget
fun canBind(item: Class<out CatalogItem>): Boolean
...
}
}
20. Plugin Architecture
API
Extensible
Feature
API
Extensible
CORE
(stable)
Feature
API
...
...
API
API
Extensible
Feature
FEATURES
(unstable)
21. Evolving the Core
Feature A
Feature B
Implementation
API
Feature C
...
22. Target Architecture
API
Implementation
Extensible Core
Extensible
Extension
API
Implementation
Implementation
Extensible
API
Extension
Extension
Extension
...
...
CORE
Implementation
(unstable)
CORE API
(stable)
Feature
(unstable)
23. Where we are
●
Features on the hot path are modularized and most of the others are
extracted from the monolith
● Incremental feature development is mostly smooth
● Core needs to be decoupled and splitted further
● Modularize the remaining features in the monolith
24. Number of modules by year
Is growing…
25. Challenges and learnings
● Splitting the monolith is not easy ⇒ extract code first and then decouple
● Modularization best practices written for smaller apps do not necessary apply
to bigger ones
● Cacheability issues ⇒ single module triggering recompilation of others
● Build configurations management
● Defining API/contract(s) in the core flexible enough for features, but without
too much boilerplate
26. Trade-offs
Pros
●
●
Impact analysis based on modules to speed-up test suite
Easy to configure GitHub codeowners
Cons
●
●
●
Configuration time grows with number of modules
Low coupling requires integration testing to identify issues
Running tests on Firebase TestLab becomes slower and less effective with
many modules
27. Thank you
And we are hiring!
28. FashionStore App
-
-
-
Screenshots
Main features
cross-feature functionalities
29.
30.
31.
32. Teams
Premise Contribution
Model
4 for platform
12 for features
P
L
A
T
F
O
R
M
T
E
A
M
S
Pillar 1
Pillar 2
…
Program 1
…
Program
Pillar
33. Ownership examples