Compare commits
10 commits
c4f07e786a
...
219208f0cd
Author | SHA1 | Date | |
---|---|---|---|
|
219208f0cd | ||
|
7d06d02d6e | ||
92bf1e8934 | |||
50afdfaa7e | |||
c706363428 | |||
7c87b04e23 | |||
211fdec57f | |||
d31ec48711 | |||
e0f5e8d04f | |||
9d81226291 |
9 changed files with 229 additions and 1 deletions
18
adr-provs/ddd-structure.md
Normal file
18
adr-provs/ddd-structure.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
# ddd structure
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
We wanted to have a consistent structure.
|
||||
|
||||
## Decision
|
||||
|
||||
* We preliminarily use the ddd structure: application / domain / infrastructure
|
||||
* Reservation 1: find a better name for domain
|
||||
* Reservation 2: decide what to put in domain / what to cover with unit tests
|
||||
|
||||
|
||||
|
24
adr-provs/ddd-validation.md
Normal file
24
adr-provs/ddd-validation.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
# ddd-validation
|
||||
|
||||
## Status
|
||||
|
||||
to be discussed
|
||||
|
||||
## Context
|
||||
|
||||
We want express validity on domain objects. Clear described validity helps on
|
||||
* avoid many redundant and unnecessary (null-)checks spread around in the code
|
||||
* collects all validity constraints to one defined place
|
||||
|
||||
### Principles affected
|
||||
|
||||
* Check the domain borders
|
||||
* Do not tie validation to object creation / serialization
|
||||
* propagate validation through aggregates
|
||||
|
||||
![ddd-validation](ddd-validation.png)
|
||||
|
||||
### see also:
|
||||
* [Fowler] Do not use exceptions for validation: https://martinfowler.com/articles/replaceThrowWithNotification.html
|
||||
* [Fowler] Contextual Validation: https://martinfowler.com/bliki/ContextualValidation.html
|
||||
* [Vladimir Khorikov] Some ideas for validation in DDD: https://enterprisecraftsmanship.com/posts/validation-and-ddd/
|
BIN
adr-provs/ddd-validation.png
Normal file
BIN
adr-provs/ddd-validation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
13
adr-provs/materialized-configuration.md
Normal file
13
adr-provs/materialized-configuration.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# partial execution of provs
|
||||
|
||||
## Status
|
||||
|
||||
accepted
|
||||
|
||||
## Context
|
||||
|
||||
Configuration for our provisioning software provs.
|
||||
|
||||
## Decision
|
||||
|
||||
We provide a materialized configuration (represented by classes or schema). Configuration is read at application start and injected into services / components (see https://martinfowler.com/articles/injection.html).
|
19
adr-provs/one-layer-of-configuration.md
Normal file
19
adr-provs/one-layer-of-configuration.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# One layer of configuration
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
|
||||
In configuration management often convention code is mixed-up with installation and configuration code.
|
||||
In order to enable reuse we discussed whether we want to separate convention from installation and configuration code.
|
||||
|
||||
## Decision
|
||||
|
||||
* To keep it simple, we follow the mixup strategy.
|
||||
|
||||
## Consequence
|
||||
|
||||
* We use only one layer of configuration
|
||||
* We are the primary intended user
|
19
adr-provs/partial-execution.md
Normal file
19
adr-provs/partial-execution.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# partial execution of provs
|
||||
|
||||
## Status
|
||||
|
||||
to be discussed
|
||||
|
||||
## Context
|
||||
|
||||
We want to be able to execute single provision steps to apply partial installation / configuration.
|
||||
|
||||
### Options
|
||||
1. By CLI and specify ClassAndFunction
|
||||
2. Switch on cli per parameter / mapping in code from parameter to function
|
||||
3. Per KotlinScript file
|
||||
4. Configurable in the configuration
|
||||
|
||||
General points to keep in mind:
|
||||
- Dependencies
|
||||
- Transport of credentials
|
34
adr-provs/quasi-idempotence.md
Normal file
34
adr-provs/quasi-idempotence.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Quasi idempotence
|
||||
|
||||
Idempotence means you can execute a function multiple times and always get the same result.
|
||||
|
||||
In real world idempotence typically is difficult because of three aspects:
|
||||
|
||||
1. Equality hard to define
|
||||
2. There are unreflected changes in functions input
|
||||
3. Function has side effects
|
||||
|
||||
For intentionally side effect executing functions we introduce "quasi idempotence". To avoid ambiguousness we have to define on which attribute we recognize former executions.
|
||||
|
||||
## Status
|
||||
|
||||
Approved.
|
||||
|
||||
## Context
|
||||
|
||||
Software installation with provs. In case of temporal broken external dependencies we want to be able to do another installation over the previous partially broken one.
|
||||
|
||||
We follow the principle "build from scratch", so we leave the question of software version updates unconsidered here.
|
||||
|
||||
## Consequence
|
||||
|
||||
1. add / change (a line) in existing files
|
||||
* Solution: Query for changed location respecting the file type / format and skip if it was already performed. We try to avoid this case and use separate files instead of modifying existing ones.
|
||||
2. installation of an single / directory file
|
||||
* Solution: If the file/directory exists, we consider installation successful and skip this step in another installation run
|
||||
3. installation of many files/directories
|
||||
* Solution: If the last file/directory exists, we consider installation successful and skip this step in another installation run - this is useful in order to skip time consuming steps. For fast / trivial steps we can choose solution 2.
|
||||
4. install apt/deb package
|
||||
* Solution: Query whether package (name without version) is installed (either implicitly e.g. in case of apt or explicitly in other cases to avoid unnecessary downloads etc)
|
||||
5. running docker containers
|
||||
* Solution: Query whether container with name (we have to provide the name on container start) is already running
|
101
principles/ObjectValidation.md
Normal file
101
principles/ObjectValidation.md
Normal file
|
@ -0,0 +1,101 @@
|
|||
# Object validation
|
||||
|
||||
Validation of objects is essential for the quality of object-oriented programs.
|
||||
|
||||
This page provides a rough overview of different techniques and strategies around object validation.
|
||||
|
||||
## Basics
|
||||
|
||||
### Object types
|
||||
The appropriate kind of validation may differ on the kind of object, whether it is
|
||||
* mutable or
|
||||
* immutable
|
||||
|
||||
### Validation results
|
||||
|
||||
Validation results can be divided into:
|
||||
* **Detailed**: containing a list of violations
|
||||
* **Simple**: reporting just one violation (or even only success/failure), either with a simple or a generic message
|
||||
|
||||
### Technical possibilities
|
||||
Most languages are offering the following possibilities for failure handling:
|
||||
* Return values
|
||||
* Exceptions
|
||||
|
||||
### Context
|
||||
|
||||
Validations can be
|
||||
* context-dependent
|
||||
* context-independent
|
||||
|
||||
### Validation time
|
||||
* Before object creation
|
||||
* After creation (but before actual usage of the data)
|
||||
|
||||
### Validation patterns
|
||||
* Validation on existing objects/states during business operations (i.e. after object creation) (see https://enterprisecraftsmanship.com/posts/validation-and-ddd/) :
|
||||
* validate / isValid methods (backdraw: race conditions can lead to invalid state)
|
||||
* in application services (backdraw: potential business logic leakage)
|
||||
* TryExecute (backdraw: no CQRS separation: potential state change AND returning data (i.e. error message))
|
||||
* Execute / CanExecute => call separately „Can“- and „execute“-method, (partial) state is stored locally which means no race conditions can lead to an invalid state
|
||||
* Validation during object creation (avoids invalid objects), without public validation method
|
||||
* In constructor
|
||||
* In factory method (e.g. create method)
|
||||
* In Factory
|
||||
* In Builder
|
||||
* Validation before object creation with public validation method (avoids invalid objects, allows CQRS and detailed results):
|
||||
* With (static/class level) validation AND factory method - (https://savoiragile.com/2012/06/28/english-object-validation-on-immutable-objects/ & https://reflectoring.io/java-immutables/ )
|
||||
* Using Essence pattern (https://stackoverflow.com/questions/9776193/good-practice-to-validate-immutable-values-objects )
|
||||
* Also Factory and Builder pattern could be added with a validate method (https://stackoverflow.com/questions/16221010/should-the-factory-pattern-contain-validation-logic ), but does not seem very common
|
||||
|
||||
|
||||
## Potential strategies
|
||||
|
||||
When putting the basics above together, you might consider the strategies below.
|
||||
|
||||
### For mutable or context-dependent objects
|
||||
Use strategies for validations **after** object creation
|
||||
(from https://enterprisecraftsmanship.com/posts/validation-and-ddd/):
|
||||
* The Execute / TryExecute pattern works best for task-based scenarios.
|
||||
* For CRUD scenarios, you need to choose between Execute / TryExecute and validation in application services. The choice comes down to purity versus ease of implementation.
|
||||
|
||||
### Immutable and context-independent objects
|
||||
|
||||
Use validations **before** object creation
|
||||
(first, you may want to validate as early as possible,
|
||||
and secondly, it normally makes no sense to create object that never will be valid.)
|
||||
|
||||
* Factory method AND validation method (for less complex cases)
|
||||
* Note: validation method must be static/at class level
|
||||
* Essence pattern (for more complex cases)
|
||||
|
||||
### Validation results
|
||||
Consider
|
||||
* Detailed results (containing a list of violations)
|
||||
* for crud-y operations e.g. when using multi-field input
|
||||
* Simple results
|
||||
* if detailed results would add no benefits, e.g. for task-based operations (if user just wants to execute a task and/or just wants to know if the task was successful or not resp. why not)
|
||||
|
||||
### Technical mechanisms
|
||||
|
||||
* Return values
|
||||
* for “expected” failures
|
||||
* Exceptions
|
||||
* for “unexpected” failures
|
||||
|
||||
https://stackoverflow.com/questions/99683/which-and-why-do-you-prefer-exceptions-or-return-codes
|
||||
https://stackoverflow.com/questions/5460101/choosing-between-exception-and-return-value
|
||||
https://enterprisecraftsmanship.com/posts/error-handling-exception-or-result/
|
||||
|
||||
|
||||
---
|
||||
###Appendix
|
||||
|
||||
Object creation (patterns, etc):
|
||||
* Constructor
|
||||
* Factory method (e.g. create method)
|
||||
* Factory
|
||||
* Builder
|
||||
* Essence
|
||||
* Other creational patterns: Prototype, Object Pool, Abstract Factory, Singleton
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Clear execution feedback
|
||||
# Clear results feedback
|
||||
|
||||
While we always hope for success, we all know too well that things can go wrong with software.
|
||||
To be able to solve potential problems it is important to get clear information e.g. about the steps performed and even more important about where it might gone wrong and especially why.
|
||||
|
|
Loading…
Reference in a new issue