Compare commits
No commits in common. "219208f0cdca4108f314d7c9463b3a8bd61c83d9" and "c4f07e786a1a4b8a0773433e09cddd81bacc5258" have entirely different histories.
219208f0cd
...
c4f07e786a
9 changed files with 1 additions and 229 deletions
|
@ -1,18 +0,0 @@
|
||||||
# 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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
# 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/
|
|
Binary file not shown.
Before Width: | Height: | Size: 60 KiB |
|
@ -1,13 +0,0 @@
|
||||||
# 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).
|
|
|
@ -1,19 +0,0 @@
|
||||||
# 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
|
|
|
@ -1,19 +0,0 @@
|
||||||
# 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
|
|
|
@ -1,34 +0,0 @@
|
||||||
# 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
|
|
|
@ -1,101 +0,0 @@
|
||||||
# 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 results feedback
|
# Clear execution feedback
|
||||||
|
|
||||||
While we always hope for success, we all know too well that things can go wrong with software.
|
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.
|
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