Skip to content

Commit affc14a

Browse files
authored
Merge pull request #612 from DirectXMan12/docs/principals
📖 Elaborate on the design pricipals of KB
2 parents c2276b8 + e328fd8 commit affc14a

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

DESIGN.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# KubeBuilder Design Principals
2+
3+
This lays out some of the guiding design principals behind the KubeBuilder
4+
project and its various components.
5+
6+
## Overarching
7+
8+
* **Libraries Over Code Generation**: Generated code is messy to maintain,
9+
hard for humans to change and understand, and hard to update. Library
10+
code is easy to update (just increase your dependency version), easier
11+
to version using existing mechanisms, and more concise.
12+
13+
* **Copy-pasting is bad**: Copy-pasted code suffers from similar problems
14+
as code generation, except more accutely. Copy-pasted code is nearly
15+
impossible to easy update, and frequently suffers from bugs and
16+
misunderstandings. If something is being copy-pasted, it should
17+
refactored into a library component or remote
18+
[kustomize](https://sigs.k8s.io/kustomize) base.
19+
20+
* **Common Cases Should Be Easy**: The 80-90% common cases should be
21+
simple and easy for users to understand.
22+
23+
* **Uncommon Cases Should Be Possible**: There shouldn't be situations
24+
where it's downright impossible to do something within
25+
controller-runtime or controller-tools. It may take extra digging or
26+
coding, and it may involve interoperating with lower-level components,
27+
but it should be possible without unreasonable friction.
28+
29+
## KubeBuilder
30+
31+
* **KubeBuilder Has Opinions**: KubeBuilder exists as an opinionated
32+
project generator. It should strive to give users a reasonable project
33+
layout that's simple enough to understand when getting started, but
34+
provides room to grow. It might not match everyone's opinions, but it
35+
should strive to be useful to most.
36+
37+
* **Batteries Included**: KubeBuilder projects should contain enough
38+
deployment information to reasonably develop and run the scaffolded
39+
project. This includes testing, deployment files, and development
40+
infrastructure to go from an code to running containers.
41+
42+
## controller-tools and controller-runtime
43+
44+
* **Sufficient But Composable**: controller-tools and controller-runtime
45+
should be sufficient for building a custom controller by hand. While
46+
scaffolding and additional libraries may make life easier, building
47+
without should be as painless as possible. That being said, they should
48+
strive to be usable as building blocks for higher-level libraries as
49+
well.
50+
51+
* **Self-Sufficient Docs**: controller-tools and controller-runtime should
52+
strive to have self-sufficient docs (i.e. documentation that doesn't
53+
require reading other libraries' documentation for common use cases).
54+
Examples should be plentiful.
55+
56+
* **Contained Arcana**: Developers should not need to be experts in
57+
Kubernetes API machinery to develop controllers, but those familiar with
58+
Kubernetes API machinery should not feel out of place. Abstractions
59+
should be intuitive to new users but feel familiar to experienced ones.
60+
Abstractions should embrace the concepts of Kubernetes (e.g. declarative
61+
idemptotent reconcilers) while simplifying the details.
62+
63+
## controller-runtime
64+
65+
* **Abstractions Should Be Layered**: Abstractions should be built on top
66+
of lower layers, such that advanced users can write custom logic while
67+
still working within the existing model. For instance, the controller
68+
builder is built on top of the event, source, and handler helpers, which
69+
are in turn built for use with the event, source, and handler
70+
interfaces.
71+
72+
* **Repetitive Stress Injuries Are Bad**:
73+
When possible, commonly used pieces should be exposed in a way that
74+
enables clear, concise code. This includes aliasing groups of
75+
functionality under "alias" or "prelude" packages to avoid having 40
76+
lines of imports, including common idioms as flexible helpers, and
77+
infering resource information from the user's object types in client
78+
code.
79+
80+
* **A Little Bit of Magic Goes a Long Way**: In absence of generics,
81+
reflection is acceptible, especially when it leads to clearer, conciser
82+
code. However, when possible interfaces that use reflection should be
83+
designed to avoid requiring the end-developer to use type assertions,
84+
string splitting, which are error-prone and repetitive. These should be
85+
dealt with inside controller-runtime internals.
86+
87+
* **Defaults Over Constructors**: When not a huge performance impact,
88+
favor auto-defaulting and `Options` structs over constructors.
89+
Constructors quickly become unclear due to lack of names associatiated
90+
with values, and don't work well with optional values.
91+
92+
## Development
93+
94+
* **Words Are Better Than Letters**: Don't abbreviate variable names
95+
unless it's blindingly obvious what they are (e.g. `ctx` for `Context`).
96+
Single- and double-letter method receivers are acceptable, but single-
97+
and double-letter variables quickly become confusing the longer a code
98+
block gets.
99+
100+
* **Well-commented code**: Code should be commented and given Godocs, even
101+
private methods and functions. It may *seem* obvious what they do at the
102+
time and why, but you might forget, and other will certainly come along.
103+
104+
* **Test Behaviors**: Test cases should be comprehensible as sets of
105+
expected behaviors. Test cases read without code (e.g. just using `It`,
106+
`Describe`, `Context`, and `By` lines) should still be able to explain
107+
what's required of the tested interface. Testing behaviors makes
108+
internal refactors easier, and makes reading tests easier.
109+
110+
* **Real Components Over Mocks**: Avoid mocks and recording actions. Mocks
111+
tend to be brittle and gradually become more complicated over time (e.g.
112+
fake client implementations tend to grow into poorly-written, incomplete
113+
API servers). Recording of actions tends to lead to brittle tests that
114+
requiring changing during refactors. Instead, test that the end desired
115+
state is correct. Test the way the world should be, without caring how
116+
it got there, and provide easy ways to set up the real components so
117+
that mocks aren't required.

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ Building APIs using CRDs, Controllers and Admission Webhooks.
5454

5555
## Philosophy
5656

57+
See [DESIGN.md](DESIGN.md) for the guiding principals of the various KubeBuilder projects.
58+
59+
TL;DR:
60+
5761
Provide clean library abstractions with clear and well exampled godocs.
5862

5963
- Prefer using go *interfaces* and *libraries* over relying on *code generation*

0 commit comments

Comments
 (0)