├── .gitignore
├── .remarkignore
├── _hooks
├── README.md
└── pre-commit
├── _website
├── static
│ ├── favicon.ico
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── mstile-144x144.png
│ ├── mstile-150x150.png
│ ├── mstile-310x150.png
│ ├── mstile-310x310.png
│ ├── mstile-70x70.png
│ ├── apple-touch-icon.png
│ ├── img
│ │ ├── mistermicheels.png
│ │ └── mistermicheels.svg
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── browserconfig.xml
│ ├── _redirects
│ ├── site.webmanifest
│ └── safari-pinned-tab.svg
├── babel.config.js
├── README.md
├── src
│ ├── pages
│ │ └── index.js
│ └── css
│ │ └── custom.css
├── .gitignore
├── docs-static
│ └── about
│ │ ├── contributing.md
│ │ └── about-note.md
├── package.json
├── goatcounter-plugin.js
├── extended-favicon-plugin.js
├── embedded-font-awesome-icons-plugin.js
└── docusaurus.config.js
├── web
├── css
│ ├── _img
│ │ ├── Grids
│ │ │ ├── grid.png
│ │ │ ├── full-bleed.png
│ │ │ ├── holy-grail.png
│ │ │ └── grid-layout-example.png
│ │ ├── Flexbox
│ │ │ └── flex-model.png
│ │ └── Box-model
│ │ │ ├── alternate-box-model.png
│ │ │ └── standard-box-model.png
│ ├── README.md
│ ├── Grids.md
│ ├── Units.md
│ ├── Responsive-design.md
│ ├── Browser-compatibility.md
│ ├── Flexbox.md
│ ├── Naming-classes.md
│ ├── Selectors.md
│ └── Positioning.md
├── README.md
└── Cookies-web-storage.md
├── java
├── _img
│ ├── Exceptions
│ │ └── exception-hierarchy.png
│ └── Java-Platform-Module-System
│ │ ├── access-modifiers.png
│ │ ├── jdk-jar-before-modules.png
│ │ ├── jdk-jars-after-modules.png
│ │ └── jdk-modules-dependencies.png
├── concurrency-details
│ ├── README.md
│ ├── Threads.md
│ └── Locking.md
├── README.md
└── Optional.md
├── processes-techniques
├── _img
│ ├── Testing
│ │ ├── test-pyramid.jpg
│ │ └── testing-quadrant.png
│ ├── Refactoring
│ │ └── mikado-method-graph.png
│ ├── Trunk-Based-Development
│ │ ├── feature-branch.png
│ │ ├── branch-for-release.png
│ │ ├── release-from-trunk.png
│ │ └── release-from-trunk-then-branch.png
│ └── Dealing-with-uncertainty
│ │ └── uncertainty-framework.png
├── testing-details
│ ├── README.md
│ ├── Testing-patterns.md
│ └── Testing-after-production.md
├── README.md
├── Small-commits-pull-requests.md
└── Dealing-with-uncertainty.md
├── _scripts
├── remark-validate-external-links.config.json
├── replace-in-file.config.js
├── remark-validate-internal-links.config.json
├── remark-write-tocs-and-format.config.json
├── serve-built-website.js
└── generate-sitemap.js
├── architecture-design
├── oo-design
│ ├── _img
│ │ ├── SOLID-principles
│ │ │ ├── observer.png
│ │ │ ├── dip-after.png
│ │ │ ├── dip-before.png
│ │ │ ├── isp-after.png
│ │ │ ├── isp-before.png
│ │ │ ├── srp-after.png
│ │ │ ├── srp-before.png
│ │ │ ├── ocp-after-adding-functionality.png
│ │ │ └── ocp-before-adding-functionality.png
│ │ └── Composition-over-inheritance
│ │ │ ├── abstract-situation-1.png
│ │ │ ├── abstract-situation-2.png
│ │ │ ├── abstract-solution-1.png
│ │ │ └── abstract-solution-2.png
│ ├── README.md
│ └── Avoiding-fat-service-classes.md
├── _img
│ ├── Architecture-people
│ │ └── communication-paths.png
│ └── Deployable-components
│ │ └── cohesion-principles-tension-diagram.jpg
├── visualizing-architecture
│ ├── _img
│ │ ├── C4-model
│ │ │ ├── c4-code.png
│ │ │ ├── c4-hierarchy.png
│ │ │ ├── c4-dynamic-diagram.png
│ │ │ ├── c4-component-diagram.png
│ │ │ ├── c4-container-diagram.png
│ │ │ ├── c4-deployment-diagram.png
│ │ │ ├── c4-system-context-diagram.png
│ │ │ └── c4-system-landscape-diagram.png
│ │ └── Dependency-analysis-tools
│ │ │ ├── static-dependency-visualization.png
│ │ │ └── interactive-dependency-visualization.png
│ ├── README.md
│ └── Dependency-analysis-tools.md
├── reference-architectures
│ ├── _img
│ │ ├── Microservices
│ │ │ ├── micro-frontend.png
│ │ │ ├── microservices.png
│ │ │ └── monolithic-frontend.png
│ │ ├── Clean-Architecture
│ │ │ ├── clean-architecture.jpg
│ │ │ └── clean-architecture-boundaries.jpg
│ │ ├── Layered-architecture
│ │ │ ├── layered-architecture.png
│ │ │ └── open-closed-layers.png
│ │ └── Package-by-feature-or-component
│ │ │ ├── package-by-feature.png
│ │ │ ├── package-by-component.png
│ │ │ └── reshaped-testing-pyramid.png
│ ├── README.md
│ └── Package-by-feature-or-component.md
├── architectural-boundaries-details
│ ├── _img
│ │ └── Separation-mechanisms
│ │ │ ├── facade-pattern.jpg
│ │ │ ├── strategy-pattern.png
│ │ │ └── clean-architecture-boundary.jpg
│ ├── README.md
│ ├── Boundaries-duplication.md
│ ├── Horizontal-vertical-separation.md
│ ├── Boundaries-web.md
│ ├── Boundaries-database.md
│ └── Boundaries-third-party-dependencies.md
├── Inversion-of-control.md
├── README.md
├── Exception-handling.md
├── Humble-Object-pattern.md
└── Duplication.md
├── javascript
├── _img
│ └── Object-prototypes-classes
│ │ └── object-oriented-delegation-oriented.png
├── typescript
│ ├── README.md
│ ├── Conditional-types.md
│ ├── Index-types.md
│ ├── Nullable-types-optional-parameters-properties.md
│ └── Type-guards.md
├── README.md
└── Spread-syntax-rest-parameters-destructuring.md
├── soft-skills
└── README.md
├── data
├── sql
│ ├── README.md
│ └── ACID.md
├── README.md
└── CAP-theorem.md
├── mindset
├── README.md
├── Ask-dumb-questions.md
└── It-depends.md
├── CONTRIBUTING.md
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/.remarkignore:
--------------------------------------------------------------------------------
1 | _hooks
2 | _scripts
3 | _website
4 | node_modules
--------------------------------------------------------------------------------
/_hooks/README.md:
--------------------------------------------------------------------------------
1 | Make git use these hooks by executing `git config core.hooksPath _hooks` (requires Git 2.9)
2 |
--------------------------------------------------------------------------------
/_website/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/favicon.ico
--------------------------------------------------------------------------------
/web/css/_img/Grids/grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/web/css/_img/Grids/grid.png
--------------------------------------------------------------------------------
/_website/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3 | };
4 |
--------------------------------------------------------------------------------
/_website/static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/favicon-16x16.png
--------------------------------------------------------------------------------
/_website/static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/favicon-32x32.png
--------------------------------------------------------------------------------
/_website/static/mstile-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/mstile-144x144.png
--------------------------------------------------------------------------------
/_website/static/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/mstile-150x150.png
--------------------------------------------------------------------------------
/_website/static/mstile-310x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/mstile-310x150.png
--------------------------------------------------------------------------------
/_website/static/mstile-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/mstile-310x310.png
--------------------------------------------------------------------------------
/_website/static/mstile-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/mstile-70x70.png
--------------------------------------------------------------------------------
/web/css/_img/Grids/full-bleed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/web/css/_img/Grids/full-bleed.png
--------------------------------------------------------------------------------
/web/css/_img/Grids/holy-grail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/web/css/_img/Grids/holy-grail.png
--------------------------------------------------------------------------------
/_website/static/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/apple-touch-icon.png
--------------------------------------------------------------------------------
/web/css/_img/Flexbox/flex-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/web/css/_img/Flexbox/flex-model.png
--------------------------------------------------------------------------------
/_website/static/img/mistermicheels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/img/mistermicheels.png
--------------------------------------------------------------------------------
/_website/static/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/android-chrome-192x192.png
--------------------------------------------------------------------------------
/_website/static/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/_website/static/android-chrome-512x512.png
--------------------------------------------------------------------------------
/java/_img/Exceptions/exception-hierarchy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/java/_img/Exceptions/exception-hierarchy.png
--------------------------------------------------------------------------------
/web/css/_img/Grids/grid-layout-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/web/css/_img/Grids/grid-layout-example.png
--------------------------------------------------------------------------------
/web/css/_img/Box-model/alternate-box-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/web/css/_img/Box-model/alternate-box-model.png
--------------------------------------------------------------------------------
/web/css/_img/Box-model/standard-box-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/web/css/_img/Box-model/standard-box-model.png
--------------------------------------------------------------------------------
/processes-techniques/_img/Testing/test-pyramid.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/processes-techniques/_img/Testing/test-pyramid.jpg
--------------------------------------------------------------------------------
/processes-techniques/_img/Testing/testing-quadrant.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/processes-techniques/_img/Testing/testing-quadrant.png
--------------------------------------------------------------------------------
/_scripts/remark-validate-external-links.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": {
3 | "remark-frontmatter": {},
4 | "remark-lint-no-dead-urls": {}
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/java/_img/Java-Platform-Module-System/access-modifiers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/java/_img/Java-Platform-Module-System/access-modifiers.png
--------------------------------------------------------------------------------
/_scripts/replace-in-file.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | files: ["**/*.md"],
3 | ignore: ["node_modules/**/*.*", "_*/**/*.*"],
4 | from: /\t/g,
5 | to: " "
6 | };
7 |
--------------------------------------------------------------------------------
/processes-techniques/_img/Refactoring/mikado-method-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/processes-techniques/_img/Refactoring/mikado-method-graph.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/observer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/observer.png
--------------------------------------------------------------------------------
/java/_img/Java-Platform-Module-System/jdk-jar-before-modules.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/java/_img/Java-Platform-Module-System/jdk-jar-before-modules.png
--------------------------------------------------------------------------------
/java/_img/Java-Platform-Module-System/jdk-jars-after-modules.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/java/_img/Java-Platform-Module-System/jdk-jars-after-modules.png
--------------------------------------------------------------------------------
/_hooks/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # run pre-commit scripts and exit if they fail
4 | npm run pre-commit || exit 1
5 |
6 | # make sure any changes made by scripts are committed
7 | git add --all
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/dip-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/dip-after.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/dip-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/dip-before.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/isp-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/isp-after.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/isp-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/isp-before.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/srp-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/srp-after.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/srp-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/srp-before.png
--------------------------------------------------------------------------------
/java/_img/Java-Platform-Module-System/jdk-modules-dependencies.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/java/_img/Java-Platform-Module-System/jdk-modules-dependencies.png
--------------------------------------------------------------------------------
/architecture-design/_img/Architecture-people/communication-paths.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/_img/Architecture-people/communication-paths.png
--------------------------------------------------------------------------------
/processes-techniques/_img/Trunk-Based-Development/feature-branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/processes-techniques/_img/Trunk-Based-Development/feature-branch.png
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/C4-model/c4-code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/C4-model/c4-code.png
--------------------------------------------------------------------------------
/processes-techniques/_img/Trunk-Based-Development/branch-for-release.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/processes-techniques/_img/Trunk-Based-Development/branch-for-release.png
--------------------------------------------------------------------------------
/processes-techniques/_img/Trunk-Based-Development/release-from-trunk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/processes-techniques/_img/Trunk-Based-Development/release-from-trunk.png
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/C4-model/c4-hierarchy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/C4-model/c4-hierarchy.png
--------------------------------------------------------------------------------
/processes-techniques/_img/Dealing-with-uncertainty/uncertainty-framework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/processes-techniques/_img/Dealing-with-uncertainty/uncertainty-framework.png
--------------------------------------------------------------------------------
/_scripts/remark-validate-internal-links.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": {
3 | "remark-frontmatter": {},
4 | "remark-validate-links": {
5 | "repository": false
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Microservices/micro-frontend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Microservices/micro-frontend.png
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Microservices/microservices.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Microservices/microservices.png
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/C4-model/c4-dynamic-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/C4-model/c4-dynamic-diagram.png
--------------------------------------------------------------------------------
/javascript/_img/Object-prototypes-classes/object-oriented-delegation-oriented.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/javascript/_img/Object-prototypes-classes/object-oriented-delegation-oriented.png
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/C4-model/c4-component-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/C4-model/c4-component-diagram.png
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/C4-model/c4-container-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/C4-model/c4-container-diagram.png
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/C4-model/c4-deployment-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/C4-model/c4-deployment-diagram.png
--------------------------------------------------------------------------------
/processes-techniques/_img/Trunk-Based-Development/release-from-trunk-then-branch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/processes-techniques/_img/Trunk-Based-Development/release-from-trunk-then-branch.png
--------------------------------------------------------------------------------
/_scripts/remark-write-tocs-and-format.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": {
3 | "remark-frontmatter": {},
4 | "remark-toc": {
5 | "heading": "contents",
6 | "tight": true
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/architecture-design/_img/Deployable-components/cohesion-principles-tension-diagram.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/_img/Deployable-components/cohesion-principles-tension-diagram.jpg
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/ocp-after-adding-functionality.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/ocp-after-adding-functionality.png
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Microservices/monolithic-frontend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Microservices/monolithic-frontend.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/Composition-over-inheritance/abstract-situation-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/Composition-over-inheritance/abstract-situation-1.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/Composition-over-inheritance/abstract-situation-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/Composition-over-inheritance/abstract-situation-2.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/Composition-over-inheritance/abstract-solution-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/Composition-over-inheritance/abstract-solution-1.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/Composition-over-inheritance/abstract-solution-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/Composition-over-inheritance/abstract-solution-2.png
--------------------------------------------------------------------------------
/architecture-design/oo-design/_img/SOLID-principles/ocp-before-adding-functionality.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/oo-design/_img/SOLID-principles/ocp-before-adding-functionality.png
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/C4-model/c4-system-context-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/C4-model/c4-system-context-diagram.png
--------------------------------------------------------------------------------
/_website/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
4 |
5 | The actual contents (plus some files depending on them) are written by higher-level scripts.
6 |
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Clean-Architecture/clean-architecture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Clean-Architecture/clean-architecture.jpg
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/C4-model/c4-system-landscape-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/C4-model/c4-system-landscape-diagram.png
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Layered-architecture/layered-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Layered-architecture/layered-architecture.png
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Layered-architecture/open-closed-layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Layered-architecture/open-closed-layers.png
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/_img/Separation-mechanisms/facade-pattern.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/architectural-boundaries-details/_img/Separation-mechanisms/facade-pattern.jpg
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/_img/Separation-mechanisms/strategy-pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/architectural-boundaries-details/_img/Separation-mechanisms/strategy-pattern.png
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Clean-Architecture/clean-architecture-boundaries.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Clean-Architecture/clean-architecture-boundaries.jpg
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Package-by-feature-or-component/package-by-feature.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Package-by-feature-or-component/package-by-feature.png
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Package-by-feature-or-component/package-by-component.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Package-by-feature-or-component/package-by-component.png
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/_img/Package-by-feature-or-component/reshaped-testing-pyramid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/reference-architectures/_img/Package-by-feature-or-component/reshaped-testing-pyramid.png
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/_img/Separation-mechanisms/clean-architecture-boundary.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/architectural-boundaries-details/_img/Separation-mechanisms/clean-architecture-boundary.jpg
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/Dependency-analysis-tools/static-dependency-visualization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/Dependency-analysis-tools/static-dependency-visualization.png
--------------------------------------------------------------------------------
/_website/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Redirect} from '@docusaurus/router';
3 | import useBaseUrl from '@docusaurus/useBaseUrl';
4 |
5 | function Home() {
6 | return ;
7 | }
8 |
9 | export default Home;
10 |
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/_img/Dependency-analysis-tools/interactive-dependency-visualization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mistermicheels/learning-notes/HEAD/architecture-design/visualizing-architecture/_img/Dependency-analysis-tools/interactive-dependency-visualization.png
--------------------------------------------------------------------------------
/_website/static/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #2b5797
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/soft-skills/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Soft skills
4 |
5 |
6 |
7 |
8 |
9 | - [Expectation management](Expectation-management.md)
10 |
--------------------------------------------------------------------------------
/_website/static/_redirects:
--------------------------------------------------------------------------------
1 | # Netlify redirects
2 | # test on https://play.netlify.com/redirects
3 |
4 | # the ! makes this a forced redirect, so Netlify redirects it even if it finds an index.html on root
5 | # https://www.netlify.com/blog/2020/04/07/creating-better-more-predictable-redirect-rules-for-spas/
6 | / /about/about/ 301!
--------------------------------------------------------------------------------
/_scripts/serve-built-website.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const app = express();
3 |
4 | const port = 3000;
5 |
6 | app.use(express.static('_website/build'));
7 |
8 | app.listen(port, () => {
9 | console.log(`Listening at http://localhost:${port}`);
10 | console.log("If necessary, you can make this publicly available through ngrok");
11 | });
--------------------------------------------------------------------------------
/java/concurrency-details/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Concurrency details
4 |
5 |
6 |
7 |
8 |
9 | - [Locking](Locking.md)
10 | - [Thread safety](Thread-safety.md)
11 | - [Threads](Threads.md)
12 |
--------------------------------------------------------------------------------
/processes-techniques/testing-details/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Testing details
4 |
5 |
6 |
7 |
8 |
9 | - [Testing after production](Testing-after-production.md)
10 | - [Testing patterns](Testing-patterns.md)
11 |
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Visualizing architecture
4 |
5 |
6 |
7 |
8 |
9 | - [C4 model](C4-model.md)
10 | - [Visual dependency analysis tools](Dependency-analysis-tools.md)
11 |
--------------------------------------------------------------------------------
/_website/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
22 | # Autogenerated by higher-level scripts
23 | /docs
24 | /static/img/from-notes
25 | /sidebars.js
26 |
--------------------------------------------------------------------------------
/architecture-design/oo-design/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Object-oriented design
4 |
5 |
6 |
7 |
8 |
9 | - [Avoiding fat service classes](Avoiding-fat-service-classes.md)
10 | - [Composition over inheritance](Composition-over-inheritance.md)
11 | - [SOLID principles](SOLID-principles.md)
12 |
--------------------------------------------------------------------------------
/data/sql/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # SQL
4 |
5 |
6 |
7 |
8 |
9 | - [ACID properties](ACID.md)
10 | - [Database normalization](Normalization.md)
11 | - [Optimistic and pessimistic locking in SQL](Optimistic-pessimistic-locking-SQL.md)
12 | - [Transaction isolation levels](Transaction-isolation-levels.md)
13 |
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Reference architectures
4 |
5 |
6 |
7 |
8 |
9 | - [Clean Architecture](Clean-Architecture.md)
10 | - [Layered architecture](Layered-architecture.md)
11 | - [Microservices](Microservices.md)
12 | - [Package by feature or component](Package-by-feature-or-component.md)
13 |
--------------------------------------------------------------------------------
/_website/static/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Learning-notes",
3 | "short_name": "Learning-notes",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#ffffff",
17 | "background_color": "#ffffff",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/javascript/typescript/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # TypeScript
4 |
5 |
6 |
7 |
8 |
9 | - [Compiler API](Compiler-API.md)
10 | - [Conditional types](Conditional-types.md)
11 | - [Index types](Index-types.md)
12 | - [Nullable types and optional parameters/properties](Nullable-types-optional-parameters-properties.md)
13 | - [Runtime type checking in TypeScript](Runtime-type-checking.md)
14 | - [Type guards](Type-guards.md)
15 |
--------------------------------------------------------------------------------
/data/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Data
4 |
5 |
6 |
7 |
8 |
9 | - [CAP theorem](CAP-theorem.md)
10 | - [Data schema migration](Data-schema-migration.md)
11 | - [SQL, NoSQL, NewSQL](SQL-NoSQL-NewSQL.md)
12 | - [**SQL**](sql/README.md)
13 | - [ACID properties](sql/ACID.md)
14 | - [Database normalization](sql/Normalization.md)
15 | - [Optimistic and pessimistic locking in SQL](sql/Optimistic-pessimistic-locking-SQL.md)
16 | - [Transaction isolation levels](sql/Transaction-isolation-levels.md)
17 |
--------------------------------------------------------------------------------
/mindset/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Mindset
4 |
5 |
6 |
7 |
8 |
9 | - [Ask the dumb questions](Ask-dumb-questions.md)
10 | - [Concepts, not code](Concepts-not-code.md)
11 | - [Fail fast](Fail-fast.md)
12 | - [Hammock-driven development](Hammock-driven-development.md)
13 | - [It depends](It-depends.md)
14 | - [It's about people](Its-about-people.md)
15 | - [Keep it simple](Keep-it-simple.md)
16 | - [Pragmatism and imperfectionism](Pragmatism-imperfectionism.md)
17 | - [Work-life balance](Work-life-balance.md)
18 |
--------------------------------------------------------------------------------
/web/css/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # CSS
4 |
5 |
6 |
7 |
8 |
9 | - [Box model](Box-model.md)
10 | - [Browser compatibility](Browser-compatibility.md)
11 | - [Flexbox](Flexbox.md)
12 | - [Grids](Grids.md)
13 | - [Inheritance, the cascade and specificity](Inheritance-cascade-specificity.md)
14 | - [Naming classes](Naming-classes.md)
15 | - [Positioning](Positioning.md)
16 | - [Responsive design](Responsive-design.md)
17 | - [Sass/SCSS](Sass-SCSS.md)
18 | - [Selectors](Selectors.md)
19 | - [Units](Units.md)
20 |
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Architectural boundaries details
4 |
5 |
6 |
7 |
8 |
9 | - [Boundaries and the database](Boundaries-database.md)
10 | - [Boundaries and duplication](Boundaries-duplication.md)
11 | - [Boundaries and third-party dependencies](Boundaries-third-party-dependencies.md)
12 | - [Boundaries and the web](Boundaries-web.md)
13 | - [Horizontal versus vertical separation](Horizontal-vertical-separation.md)
14 | - [Separation mechanisms](Separation-mechanisms.md)
15 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | This repository contains my notes regarding things I have learned over the years. Some goals I had when creating these notes:
4 |
5 | - Allow me to quickly get back up to speed on a subject that I investigated before
6 | - Help me structure my thoughts as I am learning new things
7 |
8 | In order for those goals to be achieved, it's important that I am the only one writing these notes. Therefore, I will not accept any contributions to this repository (with the exception of minor spelling, grammar and attribution fixes).
9 |
10 | If you want to build upon my work, feel free to fork this repository or use the text in any other way while providing proper attribution (a link to this repo is sufficient).
11 |
--------------------------------------------------------------------------------
/web/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Web
4 |
5 |
6 |
7 |
8 |
9 | - [Cookies and Web Storage](Cookies-web-storage.md)
10 | - [**CSS**](css/README.md)
11 | - [Box model](css/Box-model.md)
12 | - [Browser compatibility](css/Browser-compatibility.md)
13 | - [Flexbox](css/Flexbox.md)
14 | - [Grids](css/Grids.md)
15 | - [Inheritance, the cascade and specificity](css/Inheritance-cascade-specificity.md)
16 | - [Naming classes](css/Naming-classes.md)
17 | - [Positioning](css/Positioning.md)
18 | - [Responsive design](css/Responsive-design.md)
19 | - [Sass/SCSS](css/Sass-SCSS.md)
20 | - [Selectors](css/Selectors.md)
21 | - [Units](css/Units.md)
22 |
--------------------------------------------------------------------------------
/_website/docs-static/about/contributing.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Contributing
3 | ---
4 |
5 | Some goals I had when creating these notes:
6 |
7 | - Allow me to quickly get back up to speed on a subject that I investigated before
8 | - Help me structure my thoughts as I am learning new things
9 |
10 | In order for those goals to be achieved, it's important that I am the only one writing these notes. Therefore, I will not accept any contributions to the repository (with the exception of minor spelling, grammar and attribution fixes).
11 |
12 | If you want to build upon my work, feel free to fork the repository or use the text in any other way while providing proper attribution (a link to this website or the repository is sufficient).
13 |
--------------------------------------------------------------------------------
/java/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Java
4 |
5 |
6 |
7 |
8 |
9 | - [Concurrency](Concurrency.md)
10 | - [Date and Time API](Date-Time-API.md)
11 | - [Equals](Equals.md)
12 | - [Exceptions](Exceptions.md)
13 | - [Generics](Generics.md)
14 | - [Interfaces](Interfaces.md)
15 | - [Java Platform Module System](Java-Platform-Module-System.md)
16 | - [Lambda expressions](Lambda-expressions.md)
17 | - [Optional type](Optional.md)
18 | - [Overloading, overriding and method hiding](Overloading-overriding-method-hiding.md)
19 | - [Streams](Streams.md)
20 | - [**Concurrency details**](concurrency-details/README.md)
21 | - [Locking](concurrency-details/Locking.md)
22 | - [Thread safety](concurrency-details/Thread-safety.md)
23 | - [Threads](concurrency-details/Threads.md)
24 |
--------------------------------------------------------------------------------
/javascript/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # JavaScript
4 |
5 |
6 |
7 |
8 |
9 | - [Event loop](Event-loop.md)
10 | - [Object prototypes and classes](Object-prototypes-classes.md)
11 | - [Scope and closures](Scope-closures.md)
12 | - [Spread syntax, rest parameters and destructuring](Spread-syntax-rest-parameters-destructuring.md)
13 | - [The this keyword](This-keyword.md)
14 | - [**TypeScript**](typescript/README.md)
15 | - [Compiler API](typescript/Compiler-API.md)
16 | - [Conditional types](typescript/Conditional-types.md)
17 | - [Index types](typescript/Index-types.md)
18 | - [Nullable types and optional parameters/properties](typescript/Nullable-types-optional-parameters-properties.md)
19 | - [Runtime type checking in TypeScript](typescript/Runtime-type-checking.md)
20 | - [Type guards](typescript/Type-guards.md)
21 |
--------------------------------------------------------------------------------
/_website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-notes",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "docusaurus start",
7 | "start-and-expose": "docusaurus start --host 0.0.0.0",
8 | "build": "docusaurus build",
9 | "swizzle": "docusaurus swizzle",
10 | "deploy": "docusaurus deploy"
11 | },
12 | "dependencies": {
13 | "@docusaurus/core": "2.0.1",
14 | "@docusaurus/preset-classic": "2.0.1",
15 | "@mdx-js/react": "^1.6.22",
16 | "clsx": "^1.2.1",
17 | "prism-react-renderer": "^1.3.5",
18 | "react": "^17.0.2",
19 | "react-dom": "^17.0.2"
20 | },
21 | "devDependencies": {
22 | "@docusaurus/module-type-aliases": "2.0.1"
23 | },
24 | "browserslist": {
25 | "production": [
26 | ">0.5%",
27 | "not dead",
28 | "not op_mini all"
29 | ],
30 | "development": [
31 | "last 1 chrome version",
32 | "last 1 firefox version",
33 | "last 1 safari version"
34 | ]
35 | },
36 | "engines": {
37 | "node": ">=16.14"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/processes-techniques/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Processes and techniques
4 |
5 |
6 |
7 |
8 |
9 | - [Branch By Abstraction and application strangulation](Branch-by-abstraction-application-strangulation.md)
10 | - [Client-first design](Client-first-design.md)
11 | - [Code review and collaboration workflows](Code-review-collaboration.md)
12 | - [Dealing with uncertainty](Dealing-with-uncertainty.md)
13 | - [Feature flags](Feature-flags.md)
14 | - [Issue troubleshooting](Issue-troubleshooting.md)
15 | - [Managing technical debt](Managing-technical-debt.md)
16 | - [Refactoring](Refactoring.md)
17 | - [Small commits and pull requests](Small-commits-pull-requests.md)
18 | - [Static analysis](Static-analysis.md)
19 | - [Team decision-making](Team-decision-making.md)
20 | - [Testing](Testing.md)
21 | - [Trunk Based Development](Trunk-Based-Development.md)
22 | - [**Testing details**](testing-details/README.md)
23 | - [Testing after production](testing-details/Testing-after-production.md)
24 | - [Testing patterns](testing-details/Testing-patterns.md)
25 |
--------------------------------------------------------------------------------
/architecture-design/visualizing-architecture/Dependency-analysis-tools.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: An overview of using tools to analyze your codebase
3 | last_modified: 2020-11-01T12:34:21.420Z
4 | ---
5 |
6 | # Visual dependency analysis tools
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 |
12 | ## Basic idea
13 |
14 | Tools that analyze dependencies in the codebase and use that information to generate graphs, identify clusters of classes that heavily depend on each other, ...
15 |
16 | Output could be:
17 |
18 | - static images, generated based on parameters (can be useful for documentation generation)
19 | - interactively explorable visualizations
20 |
21 | Example static images: [How to easily visualize a project's dependency graph with dependency-cruiser](https://www.netlify.com/blog/2018/08/23/how-to-easily-visualize-a-projects-dependency-graph-with-dependency-cruiser/)
22 |
23 | 
24 |
25 | Example interactively explorable visualizations: [ngrev](https://github.com/mgechev/ngrev)
26 |
27 | 
28 |
29 | Note: you can use these or similar tools to restrict dependencies! See also [Static analysis - Internal dependencies](../../processes-techniques/Static-analysis.md#internal-dependencies).
30 |
--------------------------------------------------------------------------------
/_website/static/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
26 |
--------------------------------------------------------------------------------
/_website/docs-static/about/about-note.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: About these notes
3 | slug: about
4 | ---
5 |
6 | These are some notes regarding things I have learned.
7 |
8 | Each note will provide a summary of the most important points regarding the topic. This is useful for getting a higher-level understanding or refreshing your memory. If you want more details, you can use the resources at the end of the note as a curated list of resources.
9 |
10 | The actual notes are versioned in this GitHub repository . This website is generated from those notes using the lovely Docusaurus plus a bunch of custom scripts that are also in the repository. The generated site is hosted on Cloudflare Pages and search is powered by Algolia's DocSearch . Analytics are collected using the privacy-friendly GoatCounter .
11 |
--------------------------------------------------------------------------------
/_website/goatcounter-plugin.js:
--------------------------------------------------------------------------------
1 | module.exports = function (_context, _options) {
2 | return {
3 | name: "goatcounter-plugin",
4 | injectHtmlTags() {
5 | return {
6 | postBodyTags: [
7 | {
8 | tagName: "script",
9 | attributes: {
10 | type: "text/javascript",
11 | },
12 | innerHTML: `window.goatcounter = { no_events: true };
13 |
14 | window.addEventListener("click", event => {
15 | if (!window.goatcounter.count) {
16 | // GoatCounter not loaded yet
17 | return;
18 | }
19 |
20 | if (!event.target) {
21 | return;
22 | }
23 |
24 | const href = event.target.getAttribute("href");
25 |
26 | if (!href || href.startsWith("http") || href.startsWith("#")) {
27 | // no link, external link or link within current note
28 | return;
29 | }
30 |
31 | // without setTimeout, we track new path but old title when moving between notes
32 | setTimeout(() => {
33 | window.goatcounter.count();
34 | });
35 | })`,
36 | },
37 | {
38 | tagName: "script",
39 | attributes: {
40 | "data-goatcounter": "https://learning-notes.goatcounter.com/count",
41 | async: true,
42 | src: "//gc.zgo.at/count.js"
43 | },
44 | },
45 | ],
46 | };
47 | },
48 | };
49 | };
50 |
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/Boundaries-duplication.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: How architectural boundaries can create false duplication
3 | last_modified: 2020-07-11T16:56:51.566Z
4 | ---
5 |
6 | # Boundaries and duplication
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Resources](#resources)
12 |
13 | ## Basic idea
14 |
15 | Setting proper architectural boundaries can create **false duplication**, where things are the same right now but likely to change independently of each other in the future
16 |
17 | - Common with vertical slicing, where certain functionalities may start out looking similar but end up diverging significantly
18 | - Can also happen with horizontal slicing, for example the apparent duplication between a database row and the corresponding structure we send to the UI
19 | - It may be tempting to pass the database row directly to the UI, and in some cases this can be a good idea, but it isn’t hard to imagine that the structure of the data to show in the UI and the structure of the data in the DB could have to change independently of each other
20 | - Splitting into microservices can lead to some (apparent) duplication of data between databases
21 | - See also [Microservices - Data duplication and bounded contexts](../reference-architectures/Microservices.md#data-duplication-and-bounded-contexts)
22 |
23 | Trying to get rid of this kind of duplication is likely a bad idea (see also [Duplication](../Duplication.md))
24 |
25 | ## Resources
26 |
27 | - Clean Architecture (book by Robert C. Martin)
28 | - Building Evolutionary Architectures (book by Neal Ford, Rebecca Parsons and Patrick Kua) ([summary slides](http://nealford.com/downloads/Evolutionary_Architecture_Keynote_by_Neal_Ford.pdf))
29 |
--------------------------------------------------------------------------------
/_website/extended-favicon-plugin.js:
--------------------------------------------------------------------------------
1 | module.exports = function(_context, _options) {
2 | return {
3 | name: 'extended-favicon-plugin',
4 | injectHtmlTags() {
5 | return {
6 | headTags: [
7 | {
8 | tagName: 'link',
9 | attributes: {
10 | rel: 'apple-touch-icon',
11 | sizes: "180x180",
12 | href: '/apple-touch-icon.png',
13 | },
14 | },
15 | {
16 | tagName: 'link',
17 | attributes: {
18 | rel: 'icon',
19 | type: 'image/png',
20 | sizes: '32x32',
21 | href: '/favicon-32x32.png',
22 | },
23 | },
24 | {
25 | tagName: 'link',
26 | attributes: {
27 | rel: 'icon',
28 | type: 'image/png',
29 | sizes: '16x16',
30 | href: '/favicon-16x16.png',
31 | },
32 | },
33 | {
34 | tagName: 'link',
35 | attributes: {
36 | rel: 'manifest',
37 | href: '/site.webmanifest',
38 | },
39 | },
40 | {
41 | tagName: 'link',
42 | attributes: {
43 | rel: 'mask-icon',
44 | href: '/safari-pinned-tab.svg',
45 | color: '#000000',
46 | },
47 | },
48 | {
49 | tagName: 'meta',
50 | attributes: {
51 | name: 'msapplication-TileColor',
52 | content: '#2b5797',
53 | },
54 | },
55 | {
56 | tagName: 'meta',
57 | attributes: {
58 | name: 'theme-color',
59 | content: '#ffffff',
60 | },
61 | },
62 | ]
63 | };
64 | },
65 | };
66 | };
--------------------------------------------------------------------------------
/data/sql/ACID.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: An overview of the ACID properties offered by relational databases
3 | last_modified: 2020-05-30T15:54:15+02:00
4 | ---
5 |
6 | # ACID properties
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Resources](#resources)
12 |
13 | ## Basic idea
14 |
15 | ACID = acronym describing four properties that transactions in relational database must have
16 |
17 | Also provided to some extent by some NoSQL or NewSQL databases
18 |
19 | The four ACID properties:
20 |
21 | - _Atomicity_:
22 | - A transaction is treated as a single unit that either succeeds completely or fails completely. If some operation fails as part of a transaction, the entire transaction is rolled back, including the changes that other operations may have performed in the same transaction. The system must guarantee this in every situation, even if the system crashes right after a transaction is successfully committed.
23 | - _Consistency_:
24 | - The execution of the transaction must bring the database to a valid state, respecting the database’s schema
25 | - Example: no matter how many concurrent transactions are executing, you will never be able to set a foreign key from a row to another row that does not exist (but maybe did exist when you retrieved your data)
26 | - _Isolation_:
27 | - Although multiple transactions may be running concurrently, their effects on each other’s execution are limited.
28 | - Relational database systems typically provide multiple isolation levels, where higher levels protect against more concurrency-induced phenomena than lower levels. For more details, see [transaction isolation levels](./Transaction-isolation-levels.md).
29 | - _Durability_:
30 | - Once a transaction has been successfully committed, it will remain so, even if the system crashes, power is shut off, etc. right after the transaction has completed.
31 |
32 | ## Resources
33 |
34 | - [ACID (computer science)](https://en.wikipedia.org/wiki/ACID_(computer_science))
35 |
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/Horizontal-vertical-separation.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: The benefits and drawbacks of horizontal and vertical boundaries
3 | last_modified: 2020-11-28T17:53:12.418Z
4 | ---
5 |
6 | # Horizontal versus vertical separation
7 |
8 | ## Contents
9 |
10 | - [Horizontal slicing](#horizontal-slicing)
11 | - [Vertical slicing](#vertical-slicing)
12 | - [Resources](#resources)
13 |
14 | ## Horizontal slicing
15 |
16 | - Boundaries between different technical areas (layers) of the system
17 | - Example: a layer for the API, a layer the business logic and a layer for communicating with the database
18 | - Benefit: allow for technological flexibility (for example, relatively easy to switch to other kind of DB)
19 | - Drawback: single functional change is likely to affect multiple layers
20 |
21 | ## Vertical slicing
22 |
23 | - Boundaries between different functional areas of the system
24 | - Example: functionality for managing customers can be separated from functionality for placing orders
25 | - Benefit: Changes within a single functional domain can happen within a single part of the system
26 | - Especially helpful if different parts maintained by different teams!
27 | - Changes within a single functional domain can happen within a single team and coordination with other teams is only required if the communication with other functional domains needs changes as well
28 | - See [Architecture and people - Conway's law](../Architecture-people.md#conways-law)
29 | - See [microservices](../reference-architectures/Microservices.md), where different small teams each maintain one or more microservices that encapsulate a certain functional area across several layers of the technical stack, even down to the database
30 |
31 | ## Resources
32 |
33 | - Clean Architecture (book by Robert C. Martin)
34 | - Building Evolutionary Architectures (book by Neal Ford, Rebecca Parsons and Patrick Kua) ([summary slides](http://nealford.com/downloads/Evolutionary_Architecture_Keynote_by_Neal_Ford.pdf))
35 | - [Conway’s Corollary](http://www.ianbicking.org/blog/2015/08/conways-corollary.html)
36 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "scripts-with-dependencies",
3 | "version": "1.0.0",
4 | "description": "Contains script invocations and their dependencies",
5 | "scripts": {
6 | "pre-commit": "npm run check-and-write-data",
7 | "check-and-write-data": "npm run _replace-tabs && npm run _write-notes-trees && npm run _write-tocs-and-format && npm run _validate-internal-links && npm run _custom-checks-adjustments && npm run _write-website-data",
8 | "build-website": "npm run check-and-write-data && cd _website && npm run build && cd .. && npm run _generate-sitemap",
9 | "serve-built-website": "node ./_scripts/serve-built-website.js",
10 | "build-and-serve": "npm run build-website && npm run serve-built-website",
11 | "build-website-ci": "npm ci && cd _website && npm ci && cd .. && npm run build-website",
12 | "validate-external-links": "remark --rc-path _scripts/remark-validate-external-links.config.json --ignore-path .remarkignore --frail .",
13 | "_replace-tabs": "replace-in-file --configFile=_scripts/replace-in-file.config.js",
14 | "_write-notes-trees": "markdown-notes-tree --ignore CONTRIBUTING.md --linkToSubdirectoryReadme --notesBeforeDirectories",
15 | "_write-tocs-and-format": "remark --rc-path _scripts/remark-write-tocs-and-format.config.json --ignore-path .remarkignore . --output",
16 | "_validate-internal-links": "remark --rc-path _scripts/remark-validate-internal-links.config.json --ignore-path .remarkignore --frail .",
17 | "_custom-checks-adjustments": "node ./_scripts/custom-checks-adjustments.js",
18 | "_write-website-data": "node ./_scripts/write-website-data.js",
19 | "_generate-sitemap": "node ./_scripts/generate-sitemap.js"
20 | },
21 | "devDependencies": {
22 | "express": "^4.17.1",
23 | "front-matter": "^3.1.0",
24 | "fs-extra": "^9.0.0",
25 | "markdown-notes-tree": "^1.10.0",
26 | "remark-cli": "^8.0.0",
27 | "remark-frontmatter": "^2.0.0",
28 | "remark-lint-no-dead-urls": "^1.0.2",
29 | "remark-toc": "^7.0.0",
30 | "remark-validate-links": "^10.0.0",
31 | "replace-in-file": "^5.0.2",
32 | "sitemap": "^6.1.1",
33 | "unist-util-visit": "^2.0.2"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/web/css/Grids.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Grids
3 | description: The main idea of CSS Grids
4 | last_modified: 2020-12-31T13:17:37.843Z
5 | ---
6 |
7 | # Grids (CSS)
8 |
9 | ## Contents
10 |
11 | - [Basic idea](#basic-idea)
12 | - [Use cases](#use-cases)
13 | - [Holy grail layout](#holy-grail-layout)
14 | - [Full bleed layout](#full-bleed-layout)
15 | - [Resources](#resources)
16 |
17 | ## Basic idea
18 |
19 | 
20 |
21 | ([image source](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Grids))
22 |
23 | - Grid with horizontal **rows** and vertical **columns**
24 | - Row height and column width can be different per row/column
25 | - Gaps between each row and between each column called **gutters**
26 |
27 | Grid is enabled at the level of the container by setting `display: grid;` on it
28 |
29 | ## Use cases
30 |
31 | Grids are a good option whenever you want to define a two-dimensional layout for your page.
32 |
33 | Example (with indication of rows and columns as shown by [Firefox Grid Inspector](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts)):
34 |
35 | 
36 |
37 | ([image source](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Grids))
38 |
39 | ### Holy grail layout
40 |
41 | 
42 |
43 | ([image source](https://www.joshwcomeau.com/css/full-bleed/))
44 |
45 | Simple way to achieve it: [CSS Grid: Holy Grail Layout](https://www.digitalocean.com/community/tutorials/css-css-grid-holy-grail-layout)
46 |
47 | ### Full bleed layout
48 |
49 | 
50 |
51 | ([image source](https://www.joshwcomeau.com/css/full-bleed/))
52 |
53 | How to achieve it: [Full-Bleed Layout Using CSS Grid](https://www.joshwcomeau.com/css/full-bleed/)
54 |
55 | ## Resources
56 |
57 | - [CSS - The Complete Guide 2020 (incl. Flexbox, Grid & Sass)](https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/)
58 | - [Grids](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Grids)
59 | - [CSS Grid: Holy Grail Layout](https://www.digitalocean.com/community/tutorials/css-css-grid-holy-grail-layout)
60 | - [Full-Bleed Layout Using CSS Grid](https://www.joshwcomeau.com/css/full-bleed/)
61 |
--------------------------------------------------------------------------------
/web/css/Units.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Units
3 | description: An overview of the most important CSS units and some advice on when to use which
4 | last_modified: 2020-10-25T21:56:09.044Z
5 | ---
6 |
7 | # Units (CSS)
8 |
9 | ## Contents
10 |
11 | - [Types of units](#types-of-units)
12 | - [When to use what](#when-to-use-what)
13 | - [Resources](#resources)
14 |
15 | ## Types of units
16 |
17 | - Absolute: `px` (pixels) etc.
18 | - Typical example: `px` (pixels)
19 | - Drawback when using px for font size: ignores any non-standard default font size that user has configured in browser
20 | - Relative to parent element: `%`
21 | - See also [Box model](./Box-model.md)
22 | - Relative to viewport: `vh`, `vw ` (% of viewport height, % of viewport width)
23 | - See also [Box model](./Box-model.md)
24 | - Also `vmin`, `vmax` (% of smallest viewport dimension, % of largest viewport dimension)
25 | - Relative to font size
26 | - `rem`: font size of root (HTML) element (this is set by the browser by default)
27 | - `em`: font size of parent element
28 |
29 | ## When to use what
30 |
31 | Good practice (but not necessarily best in all cases):
32 |
33 | - Font size on root element
34 | - Nothing (let your browser specify it)
35 | - `%` (percentage of default font size, still increases proportionally with font size configured in browser)
36 | - Most browsers set default font size to 16px by default -> setting `62.5%` as font size on the root element will make `1 rem` equal to 10px for default browser settings, which can make calculations easier
37 | - Font size on non-root element:
38 | - `rem` (typically the safe choice)
39 | - `em` (useful when font sizes need to gradually decrease when elements are nested)
40 | - Padding and margins: `rem`
41 | - Borders: `px` (visually, it often doesn't make sense for border thickness to scale with font size)
42 | - Width and height: `%` or `vh`
43 | - Top, bottom, left, right: `%`
44 |
45 | ## Resources
46 |
47 | - [CSS - The Complete Guide 2020 (incl. Flexbox, Grid & Sass)](https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/)
48 | - [CSS values and units](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units)
49 | - [CSS units for font-size: px | em | rem](https://medium.com/code-better/css-units-for-font-size-px-em-rem-79f7e592bb97)
50 |
--------------------------------------------------------------------------------
/architecture-design/Inversion-of-control.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: What inversion of control means and why it's useful when building applications
3 | last_modified: 2020-12-31T13:17:37.794Z
4 | ---
5 |
6 | # Inversion of control
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Implementation](#implementation)
12 | - [Resources](#resources)
13 |
14 | ## Basic idea
15 |
16 | - Separate code defining **how** something is done from code defining **when** it is done
17 | - Ensure that both of these parts know as little as possible about each other
18 |
19 | Benefits:
20 |
21 | - Decoupling between "how" and "when" parts
22 | - The less they need to know about each other, the easier it is to replace/adjust one without breaking the other
23 | - More focused classes/modules
24 |
25 | ## Implementation
26 |
27 | - Events
28 | - Separate code handling events ("how" part) from code triggering events ("when part")
29 | - Dependency injection
30 | - Pass dependencies of a class/function/module as constructor arguments, method parameters, ...
31 | - "How" is defined inside the dependencies that are injected + in the code that determines which specific implementation will be injected (as opposed to the class/function/module instantiating its own dependencies)
32 | - Second part is very useful for reusability and also makes it easy to pass in specific implementations for running automated tests
33 | - "When" is defined by the code of the class/function/module that uses the dependencies
34 | - The [Template method pattern](https://en.wikipedia.org/wiki/Template_method_pattern)
35 | - Separate implementation of template method ("how" part) from logic for calling the template method ("when" part)
36 | - The [Strategy pattern](https://en.wikipedia.org/wiki/Strategy_pattern)
37 | - Strategy itself defines the "how" part, code calling strategy defines the "when" part
38 | - Good use case for dependency injection
39 |
40 | ## Resources
41 |
42 | - [Inversion of control](https://en.wikipedia.org/wiki/Inversion_of_control)
43 | - [What is Inversion of Control?](https://stackoverflow.com/questions/3058/what-is-inversion-of-control)
44 | - [Inversion of Control vs Dependency Injection](https://stackoverflow.com/questions/6550700/inversion-of-control-vs-dependency-injection)
45 | - [Template method pattern](https://en.wikipedia.org/wiki/Template_method_pattern)
46 | - [Strategy pattern](https://en.wikipedia.org/wiki/Strategy_pattern)
47 |
--------------------------------------------------------------------------------
/_website/embedded-font-awesome-icons-plugin.js:
--------------------------------------------------------------------------------
1 | module.exports = function (_context, _options) {
2 | return {
3 | name: "font-awesome-plugin",
4 | injectHtmlTags() {
5 | return {
6 | preBodyTags: [
7 | {
8 | tagName: "svg",
9 | attributes: {
10 | style: "display: none;",
11 | },
12 | innerHTML: `Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
13 | License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
14 |
15 |
16 |
17 |
18 |
19 | `
20 | },
21 | ],
22 | };
23 | },
24 | };
25 | };
26 |
--------------------------------------------------------------------------------
/architecture-design/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Architecture and design
4 |
5 |
6 |
7 |
8 |
9 | - [Architectural boundaries](Architectural-boundaries.md)
10 | - [Architectural fitness functions](Architectural-fitness-functions.md)
11 | - [Architecture and people](Architecture-people.md)
12 | - [Circular dependencies](Circular-dependencies.md)
13 | - [Deletes](Deletes.md)
14 | - [Deployable components](Deployable-components.md)
15 | - [Duplication](Duplication.md)
16 | - [Exception handling](Exception-handling.md)
17 | - [Humble Object pattern](Humble-Object-pattern.md)
18 | - [Inversion of control](Inversion-of-control.md)
19 | - [Names](Names.md)
20 | - [Separation of concerns](Separation-of-concerns.md)
21 | - [**Architectural boundaries details**](architectural-boundaries-details/README.md)
22 | - [Boundaries and the database](architectural-boundaries-details/Boundaries-database.md)
23 | - [Boundaries and duplication](architectural-boundaries-details/Boundaries-duplication.md)
24 | - [Boundaries and third-party dependencies](architectural-boundaries-details/Boundaries-third-party-dependencies.md)
25 | - [Boundaries and the web](architectural-boundaries-details/Boundaries-web.md)
26 | - [Horizontal versus vertical separation](architectural-boundaries-details/Horizontal-vertical-separation.md)
27 | - [Separation mechanisms](architectural-boundaries-details/Separation-mechanisms.md)
28 | - [**Object-oriented design**](oo-design/README.md)
29 | - [Avoiding fat service classes](oo-design/Avoiding-fat-service-classes.md)
30 | - [Composition over inheritance](oo-design/Composition-over-inheritance.md)
31 | - [SOLID principles](oo-design/SOLID-principles.md)
32 | - [**Reference architectures**](reference-architectures/README.md)
33 | - [Clean Architecture](reference-architectures/Clean-Architecture.md)
34 | - [Layered architecture](reference-architectures/Layered-architecture.md)
35 | - [Microservices](reference-architectures/Microservices.md)
36 | - [Package by feature or component](reference-architectures/Package-by-feature-or-component.md)
37 | - [**Visualizing architecture**](visualizing-architecture/README.md)
38 | - [C4 model](visualizing-architecture/C4-model.md)
39 | - [Visual dependency analysis tools](visualizing-architecture/Dependency-analysis-tools.md)
40 |
--------------------------------------------------------------------------------
/web/css/Responsive-design.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Responsive design
3 | description: Making your site look good on any device and screen
4 | last_modified: 2025-12-11T13:41:12.798Z
5 | ---
6 |
7 | # Responsive design (CSS)
8 |
9 | ## Contents
10 |
11 | - [Basic idea](#basic-idea)
12 | - [Viewport meta tag](#viewport-meta-tag)
13 | - [Media queries](#media-queries)
14 | - [Flexbox and Grids](#flexbox-and-grids)
15 | - [Testing your design](#testing-your-design)
16 | - [Resources](#resources)
17 |
18 | ## Basic idea
19 |
20 | - Goal: make your website look good on any device
21 | - Important tools:
22 | - Viewport meta tag
23 | - Media queries
24 |
25 | ## Viewport meta tag
26 |
27 | - Converts between "hardware pixels" and "software pixels", helping you support screens with different pixel densities
28 | - On a small screen with huge pixel density, you still don't want your website to for example fill only a part of the screen or show tiny text
29 | - If used correctly, a small screen with huge pixel density will appear to your CSS rules as a screen with small dimensions in terms of pixels
30 | - See also [mydevice.io](https://mydevice.alsacreations.com/) and [whatismyviewport.com](https://whatismyviewport.com/)
31 | - Doesn't change actual design, just makes sure you have sensible width and height values to base your design on
32 |
33 | Example (common, recommended version of the tag):
34 |
35 | ```html
36 |
37 | ```
38 |
39 | ## Media queries
40 |
41 | - Allow changing design based on viewport width/height
42 | - Have to define design changes yourself based on detected width/height
43 | - Widely used in CSS framworks like [Bootstrap](https://getbootstrap.com/docs/4.0/layout/grid/)
44 |
45 | Example:
46 |
47 | ```css
48 | @media screen and (min-width: 800px) {
49 | .container {
50 | margin: 1em 2em;
51 | }
52 | }
53 | ```
54 |
55 | Common approach: **mobile-first design**
56 |
57 | - First create a design that looks good on narrow-screen devices
58 | - Then use media queries to change the layout on larger screens so it looks better or makes better use of the available screen space
59 |
60 | ## Flexbox and Grids
61 |
62 | In general, [Flexbox](./Flexbox.md) and [Grids](./Grids.md) are good tools for building pages that scale with the viewport size
63 |
64 | ## Testing your design
65 |
66 | Useful tool: Chrome DevTools Device Mode
67 |
68 | See [Simulate Mobile Devices with Device Mode in Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/device-mode)
69 |
70 | ## Resources
71 |
72 | - [CSS - The Complete Guide 2020 (incl. Flexbox, Grid & Sass)](https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/)
73 | - [Responsive design](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design)
74 |
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/Boundaries-web.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: How architectural boundaries apply to the web
3 | last_modified: 2020-05-30T15:54:15+02:00
4 | ---
5 |
6 | # Boundaries and the web
7 |
8 | ## Contents
9 |
10 | - [Decoupling the domain from the web](#decoupling-the-domain-from-the-web)
11 | - [Different representations of objects](#different-representations-of-objects)
12 | - [Micro frontends](#micro-frontends)
13 | - [Resources](#resources)
14 |
15 | ## Decoupling the domain from the web
16 |
17 | One boundary that almost always makes sense to draw is the separation between your domain and the actual user interface that the user interacts with
18 |
19 | Typical to see `Controller` classes (some other terms are used as well) that take care of the interaction with the user and delegate all real work to the code implementing the actual business logic
20 |
21 | In principle, none of your business logic should be aware of how it is shown to the user, including whether or not the UI is a web UI!
22 |
23 | ## Different representations of objects
24 |
25 | Different parts of the system have different goals -> they may also need different representations of the same object!
26 |
27 | - When doing server-side rendering, it often makes sense to have a separate view model that simply holds the data to be shown
28 | - Data in the view model could be a transformed version of the data obtained from the domain model (e.g. formatting a date) or could aggregate data from several domain objects
29 | - Data returned from the API could have a different format or structure than the actual domain objects inside the business logic part of the application
30 | - Ideally, the data returned from APIs (or expected by APIs) will be aligned with what the consumers of the API care about
31 | - If your frontend is a single-page application getting data from the backend over an API, feel free to create separate representations of that data that are more comfortable for the rest of the frontend to work with
32 | - Backend is mostly about having consistent information regarding the objects in the system, while frontend is mostly about providing the user with an easy way of interacting with those objects
33 |
34 | ## Micro frontends
35 |
36 | Even in a microservices architecture, it is typical to have a backend consisting of several microservices but a single monolithic frontend on top of it
37 |
38 | An alternative are micro frontends, where the frontend is stitched together from multiple independently maintained parts. See [Microservices](../reference-architectures/Microservices.md).
39 |
40 | ## Resources
41 |
42 | - Clean Architecture (book by Robert C. Martin)
43 | - Building Evolutionary Architectures (book by Neal Ford, Rebecca Parsons and Patrick Kua) ([summary slides](http://nealford.com/downloads/Evolutionary_Architecture_Keynote_by_Neal_Ford.pdf))
44 |
--------------------------------------------------------------------------------
/mindset/Ask-dumb-questions.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Why you shouldn't be afraid of asking the "dumb" questions
3 | last_modified: 2024-11-17T18:47:03.863Z
4 | ---
5 |
6 | # Ask the dumb questions
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Some questions to ask](#some-questions-to-ask)
12 | - [Resources](#resources)
13 |
14 | ## Basic idea
15 |
16 | - Don't be afraid of asking "dumb" questions
17 | - Don't be afraid to state the obvious
18 | - Don't be afraid to look dumb
19 | - The fact that nobody else asked a similar question yet doesn't mean that the question you have in mind is dumb
20 | - It's possible that others have the same question but don't dare to ask it
21 | - It's possible that the question touches something relevant that didn't occur to anyone else before
22 | - Something that's obvious to one person might be not that obvious at all to others
23 |
24 | The value of asking "dumb" questions:
25 |
26 | - Helps validating that you're talking about the same thing and that you're on the same page
27 | - Helps making implicit assumptions explicit and validating whether they are realistic
28 | - Helps finding edge cases or holes in the logic
29 | - Helps understanding the real reason you're doing something
30 | - Helps making sure you are solving the real problem
31 | - Helps finding alternative approaches
32 | - People asking the right questions can be very valuable in guiding the discussion towards good solutions, even if those people don't provide any potential solutions themselves
33 | - Even if the answer to a question seems obvious to you and to the rest of the team, asking the question is the only way to confirm that it's indeed obvious to everybody
34 | - Even if you are somehow the only one who is out of the loop, the team is way better off with you asking dumb questions and getting the info you need than with you continuing without asking for clarification
35 |
36 | ## Some questions to ask
37 |
38 | - Why are we doing this, again?
39 | - What if ...?
40 | - Can it happen that ...?
41 | - Are we guaranteed that ...?
42 | - What problems are we looking to solve here?
43 | - What is actually the real issue?
44 | - How important is this?
45 | - How time-sensitive is this?
46 | - Is this a decision we can postpone?
47 | - What is the smallest thing we could do to immediately add value here? Any quick wins?
48 | - Do we need a full solution immediately or can we go for a partial solution or workaround in the short term?
49 | - What is the simplest approach that could possibly work?
50 | - Can we find an alternative that is simpler?
51 | - What would we actually accomplish by doing this?
52 | - Do we actually need to take any action at all?
53 |
54 | ## Resources
55 |
56 | - [68 Bits of Unsolicited Advice](https://kk.org/thetechnium/68-bits-of-unsolicited-advice/)
57 | - [The five keys to a successful Google team](https://web.archive.org/web/20221221183223/https://rework.withgoogle.com/blog/five-keys-to-a-successful-google-team/)
58 |
--------------------------------------------------------------------------------
/processes-techniques/testing-details/Testing-patterns.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Some useful patterns for writing tests or making production code more testable
3 | last_modified: 2022-01-27T17:10:03.008Z
4 | ---
5 |
6 | # Testing patterns
7 |
8 | ## Contents
9 |
10 | - [Humble Object pattern](#humble-object-pattern)
11 | - [Clock Wrapper pattern](#clock-wrapper-pattern)
12 | - [Object Mother pattern](#object-mother-pattern)
13 | - [Resources](#resources)
14 |
15 | ## Humble Object pattern
16 |
17 | - Problem: some behavior is hard to test
18 | - Example: the way data is presented in the UI
19 | - Solution:
20 | - Extract as much of the behavior as possible into an easy-to-test part
21 | - What's left is a Humble Object containing the hard-to-test stuff stripped down to the bare essence
22 |
23 | See also separate note for [Humble Object pattern](../../architecture-design/Humble-Object-pattern.md)
24 |
25 | ## Clock Wrapper pattern
26 |
27 | - Problem: Behavior depending on current time can be hard to test
28 | - Solution: Don't get current time directly, but access it through some kind of wrapper that allows you to manually set the time to a specific value for testing purposes
29 | - Alternative: Pass in current time as a parameter for code you want to keep easy to test (more functional approach)
30 | - Alternative: Some testing tools can hook into the language's default clock/timers functionality
31 | - Example: [Cypress cy.clock()](https://docs.cypress.io/guides/guides/stubs-spies-and-clocks#Clock)
32 |
33 | You can also wrap other dependencies that are hard to control or mock
34 |
35 | ## Object Mother pattern
36 |
37 | - Problem: creating data for tests can be tedious and complex
38 | - You may need to create a complex hierarchy of objects before you can create object you are interested in
39 | - Solution: set up an "Object Mother" that creates predefined standard objects with all required data
40 | - Can make sense to have a few standard objects of the same type to represent variations
41 | - Example: fresh hire "John" and long-time employee "Heather"
42 | - Standard objects become familiar to the team and sometimes even enter functional discussions
43 | - Similar to personas, but not always people: can also be insurance policies, supplier contracts, ...
44 | - Often, standard objects need a bit of additional setup for the specific test
45 | - Avoid adding new standard objects, focus on small set that team is familiar with
46 | - Can have different Object Mothers for different object types
47 | - Drawback: coupling
48 | - Many tests will depend on the exact data specified in the Object Mother
49 | - Changing the standard data can have large impact
50 |
51 | ## Resources
52 |
53 | - Martin Fowler's [Software Testing Guide](https://martinfowler.com/testing/):
54 | - [Humble Object](https://martinfowler.com/bliki/HumbleObject.html)
55 | - [Clock Wrapper](https://martinfowler.com/bliki/ClockWrapper.html)
56 | - [Object Mother](https://martinfowler.com/bliki/ObjectMother.html)
57 | - Building Microservices (book by Sam Newman)
58 |
--------------------------------------------------------------------------------
/_website/docusaurus.config.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | const path = require('path');
4 |
5 | /** @type {import('@docusaurus/types').Config} */
6 | const config = {
7 | title: 'learning-notes',
8 | tagline: 'Notes regarding things I have learned',
9 | url: 'https://learning-notes.mistermicheels.com',
10 | baseUrl: '/',
11 | trailingSlash: true,
12 | onBrokenLinks: 'ignore', // broken links are checked using other scripts
13 | onBrokenMarkdownLinks: 'ignore', // broken links are checked using other scripts
14 | favicon: 'favicon.ico',
15 | i18n: {
16 | defaultLocale: 'en',
17 | locales: ['en'],
18 | },
19 | themeConfig:
20 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
21 | ({
22 | navbar: {
23 | title: 'learning-notes',
24 | logo: {
25 | alt: 'mistermicheels logo',
26 | src: 'img/mistermicheels.svg',
27 | },
28 | items: [
29 | {
30 | href: 'https://github.com/mistermicheels/learning-notes',
31 | label: 'GitHub',
32 | position: 'left',
33 | },
34 | {
35 | href: 'https://twitter.com/mistermicheels',
36 | label: 'Twitter',
37 | position: 'left',
38 | },
39 | {
40 | href: 'https://github.com/mistermicheels/learning-notes',
41 | position: 'right',
42 | className: 'header-github-link navbar__item navbar__link',
43 | 'aria-label': 'GitHub repository',
44 | },
45 | ],
46 | },
47 | footer: {
48 | style: 'dark',
49 | copyright: `This work is licensed under a Creative Commons Attribution 4.0 International
50 | License . Website built with Docusaurus.`,
51 | },
52 | docs: {
53 | sidebar: {
54 | hideable: true,
55 | },
56 | },
57 | prism: {
58 | theme: require('prism-react-renderer/themes/github'),
59 | darkTheme: require('prism-react-renderer/themes/oceanicNext'),
60 | additionalLanguages: ["java"]
61 | },
62 | algolia: {
63 | appId: '38H0OSE8H7',
64 | apiKey: '1119242d2ba32e7ccfd08f8ae82b3efe',
65 | indexName: 'mistermicheels_learning-notes',
66 | contextualSearch: false
67 | },
68 | }),
69 |
70 | presets: [
71 | [
72 | 'classic',
73 | /** @type {import('@docusaurus/preset-classic').Options} */
74 | ({
75 | docs: {
76 | sidebarPath: require.resolve('./sidebars.js'),
77 | routeBasePath: '/',
78 | },
79 | blog: false,
80 | theme: {
81 | customCss: require.resolve('./src/css/custom.css'),
82 | },
83 | }),
84 | ],
85 | ],
86 | plugins: [
87 | path.resolve(__dirname, './extended-favicon-plugin'),
88 | path.resolve(__dirname, './embedded-font-awesome-icons-plugin'),
89 | path.resolve(__dirname, './goatcounter-plugin'),
90 | ],
91 | };
92 |
93 | module.exports = config;
94 |
--------------------------------------------------------------------------------
/_scripts/generate-sitemap.js:
--------------------------------------------------------------------------------
1 | // we generate the sitemap ourselves with some customizations
2 | // run this after the Docusaurus build so it doesn't get overwritten
3 |
4 | const { SitemapStream, streamToPromise } = require("sitemap");
5 | const path = require("path");
6 | const fsExtra = require("fs-extra");
7 | const frontMatter = require("front-matter");
8 |
9 | execute();
10 |
11 | async function execute() {
12 | try {
13 | console.log("Generating sitemap");
14 | await generateSitemap();
15 | console.log("Finished generating sitemap");
16 | } catch (error) {
17 | console.log(`Error: ${error.message}`);
18 | process.exit(1);
19 | }
20 | }
21 |
22 | async function generateSitemap() {
23 | const allPageSuffixes = getAllPageSuffixes();
24 | const sitemapBuffer = await getSitemap(allPageSuffixes);
25 | const sitemap = sitemapBuffer.toString();
26 | const sitemapPath = path.join(process.cwd(), "_website", "build", "sitemap.xml");
27 | fsExtra.outputFileSync(sitemapPath, sitemap, { encoding: "utf-8" });
28 |
29 | const robotsTxtPath = path.join(process.cwd(), "_website", "build", "robots.txt");
30 | const robotsTxtContents = "Sitemap: https://learning-notes.mistermicheels.com/sitemap.xml";
31 | fsExtra.outputFileSync(robotsTxtPath, robotsTxtContents, { encoding: "utf-8" });
32 | }
33 |
34 | function getAllPageSuffixes() {
35 | // we generated this file ourselves in write-website-data
36 | const sidebars = require("../_website/sidebars");
37 |
38 | const sidebarItems = sidebars.docs;
39 |
40 | return getDocIds(sidebarItems);
41 | }
42 |
43 | function getDocIds(sidebarItems) {
44 | const docIds = [];
45 |
46 | for (const item of sidebarItems) {
47 | if (typeof item === "string") {
48 | // we renamed about.md -> about-note.md so Docusaurus doesn't think it's a category description
49 | // however, the final URL is still about/about
50 | docIds.push(item === "about/about-note" ? "about/about" : item);
51 | } else {
52 | docIds.push(...getDocIds(item.items));
53 | }
54 | }
55 |
56 | return docIds;
57 | }
58 |
59 | async function getSitemap(allPageSuffixes) {
60 | const smStream = new SitemapStream({ hostname: 'https://learning-notes.mistermicheels.com/' });
61 |
62 | smStream.write({ url: `/`});
63 |
64 | for (const pageSuffix of allPageSuffixes) {
65 | // the slash at the end is important, links without the slash at the end get redirected
66 | smStream.write({ url: `/${pageSuffix}/`, lastmod: getLastModifiedString(pageSuffix) });
67 | }
68 |
69 | smStream.end();
70 |
71 | return streamToPromise(smStream);
72 | }
73 |
74 | function getLastModifiedString(pageSuffix) {
75 | if (pageSuffix.startsWith("about")) {
76 | return undefined;
77 | }
78 |
79 | const filePath = path.join(process.cwd(), "_website", "docs", pageSuffix + ".md")
80 | const contents = fsExtra.readFileSync(filePath, { encoding: "utf-8" });
81 | const parsedFrontMatter = frontMatter(contents);
82 |
83 | if (!parsedFrontMatter.attributes.last_modified) {
84 | return undefined;
85 | }
86 |
87 | return new Date(parsedFrontMatter.attributes.last_modified).toISOString();
88 | }
89 |
--------------------------------------------------------------------------------
/architecture-design/Exception-handling.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Some general best practices regarding exception handling
3 | last_modified: 2020-11-15T22:06:37.294Z
4 | ---
5 |
6 | # Exception handling
7 |
8 | ## Contents
9 |
10 | - [Throw early, catch late](#throw-early-catch-late)
11 | - [Providing context with exceptions](#providing-context-with-exceptions)
12 | - [Client-first design for exception classes](#client-first-design-for-exception-classes)
13 | - [Resources](#resources)
14 |
15 | ## Throw early, catch late
16 |
17 | General best practice regarding exceptions: “Throw early, catch late”. In other words: “Don’t catch an exception unless you are in the best position to do something useful with it”.
18 |
19 | For example, if an exception occurs because there is no file at a specific path, it often makes sense to propagate the exception up to the level where the path to use is determined.
20 |
21 | In general, you should only catch exceptions if:
22 |
23 | - You can perform a useful action on the exception (possibly just logging) and then rethrow it.
24 | - You can wrap the exception into a new exception that makes more sense to your caller and throw that new exception.
25 | - You can make a final decision regarding what must happen to fully handle the exception.
26 |
27 | ## Providing context with exceptions
28 |
29 | Although exceptions contain a stack trace that shows the call chain at the time the exception occurred, it is often advisable to pass additional context. Typically, you should at least provide a meaningful message explaining the intent of the operation that failed and the reason for failure. When defining custom exception classes, you can also foresee additional data being stored with the exception.
30 |
31 | If your application has logging, your exception (including stack trace) should contain enough information for creating a meaningful log message.
32 |
33 | ## Client-first design for exception classes
34 |
35 | When designing which and how many exception classes you need, try to consider the point of view of the caller.
36 |
37 | - If caller needs to handle different kinds of errors in a different way, foresee different exception classes
38 | - If caller has only one reasonable way of handling any kind of of error, only foresee a single exception class that potentially includes more details regarding the specific error that happened (in Java, exception chaining could be useful here)
39 | - If you are using a class with methods that can throw lots of different exception types, consider wrapping it in a class that delegates actual functionality to the wrapped class but catches a set of specific errors and wraps these into a single, more general error class. This is one of the techniques you can use to transform a library’s interface into an interface that makes more sense to your application, decoupling your application from the interface that the library provides.
40 |
41 | ```java
42 | public void open() {
43 | try {
44 | this.wrapped.open();
45 | } catch (Type1 | Type2 | Type3 ex) {
46 | throw new WrappedException(ex);
47 | }
48 | }
49 | ```
50 |
51 | ## Resources
52 |
53 | - Clean Code (book by Robert C. Martin)
54 | - [Exceptions: Why throw early? Why catch late?](https://softwareengineering.stackexchange.com/questions/231057/exceptions-why-throw-early-why-catch-late)
55 |
--------------------------------------------------------------------------------
/java/concurrency-details/Threads.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Threads
3 | description: Some details regarding Java threads
4 | last_modified: 2020-05-30T15:54:15+02:00
5 | ---
6 |
7 | # Threads (Java)
8 |
9 | ## Contents
10 |
11 | - [Java threads basics](#java-threads-basics)
12 | - [Thread interruption](#thread-interruption)
13 | - [Daemon threads](#daemon-threads)
14 | - [Resources](#resources)
15 |
16 | ## Java threads basics
17 |
18 | Starting a new thread manually:
19 |
20 | ```java
21 | Runnable task = () -> {
22 | // ...
23 | };
24 |
25 | Thread thread = new Thread(task);
26 | thread.start();
27 | ```
28 |
29 | Note: typically, you are better off letting executors manage thread creation for you (see [Concurrency](../Concurrency.md)
30 |
31 | Making the current thread sleep for a given amount of time:
32 |
33 | ```java
34 | Thread.sleep(millis);
35 | ```
36 |
37 | Blocking the current thread until another thread finishes:
38 |
39 | otherThread.join();
40 |
41 | A thread finishes when its `Runnable` finishes execution, either normally or by throwing an exception. If an exception was thrown, it is passed to the _uncaught exception handler_ that was set for the thread.
42 |
43 | ## Thread interruption
44 |
45 | In Java, the code running inside a thread is responsible for ensuring that it can be interrupted if needed. Each thread has a flag indicating if it is interrupted. Other threads can set this flag to true by calling the `interrupt()` method.
46 |
47 | A `Runnable` can check the _interruption status_ of its thread and then respond accordingly. Typically, this means stopping the computations.
48 |
49 | ```java
50 | Runnable task = () -> {
51 | while (moreWorkAvailable()) {
52 | if (Thread.currentThread().isInterrupted()) {
53 | return; // this ends the thread
54 | } else {
55 | // do some work
56 | }
57 | }
58 | }
59 | ```
60 |
61 | A thread might not be active at the time it is interrupted. If a thread is interrupted while inside a `wait()`, `join()` or `sleep()`, it is immediately reactivated and the interrupted method (for example the `wait()`) throws an `InterruptedException`. This is a checked exception, so you are forced to deal with it if you call `wait()`, `join()` or `sleep()`. You could just put all of your `Runnable`'s code inside a try-catch catching `InterruptedException` and doing nothing in response (ending the thread).
62 |
63 | If the thread was interrupted before a call to `wait()`, `join()` or `sleep()`, the call immediately throws an `InterruptedException`. This could mean you don't need to check for the interruption status yourself as long as you catch the `InterruptedException` when it is thrown.
64 |
65 | When you are calling a method throwing `InterruptedException` at a point where you cannot do anything sensible with it, either let it propagate upwards (by declaring the exception on your method) or at least set the current thread's interruption status to true (`Thread.currentThread().interrupt()`).
66 |
67 | ## Daemon threads
68 |
69 | You can mark a thread as a daemon thread, which indicates that the thread is just a helper for other threads and should not prevent the program from exiting. When all non-daemon threads finish, the program exits.
70 |
71 | ```java
72 | Thread thread = new Thread(task);
73 | thread.setDaemon(true);
74 | thread.start();
75 | ```
76 |
77 | ## Resources
78 |
79 | - Core Java SE 9 for the Impatient (book by Cay S. Horstmann)
80 |
--------------------------------------------------------------------------------
/_website/src/css/custom.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --ifm-color-primary: #3578e5;
3 | --ifm-color-primary-dark: #1d68e1;
4 | --ifm-color-primary-darker: #1b62d4;
5 | --ifm-color-primary-darkest: #1751af;
6 | --ifm-color-primary-light: #4e89e8;
7 | --ifm-color-primary-lighter: #5a91ea;
8 | --ifm-color-primary-lightest: #80aaef;
9 | --ifm-code-font-size: 95%;
10 | }
11 |
12 | .footer.footer--dark {
13 | --ifm-footer-background-color: #282c34;
14 | }
15 |
16 | [data-theme='dark'] {
17 | --ifm-color-primary: #79b6f2;
18 | --ifm-color-primary-dark: #58a4ef;
19 | --ifm-color-primary-darker: #479bed;
20 | --ifm-color-primary-darkest: #1680e8;
21 | --ifm-color-primary-light: #9ac8f5;
22 | --ifm-color-primary-lighter: #abd1f7;
23 | --ifm-color-primary-lightest: #dcecfc;
24 |
25 | --ifm-blockquote-color: #c0c0c0;
26 | }
27 |
28 | html[data-theme="dark"] img {
29 | filter: brightness(.95) contrast(1.05);
30 | }
31 |
32 | /* nested links in menu */
33 |
34 | .menu__link.menu__link--sublist {
35 | font-weight: bolder;
36 | }
37 |
38 | /* GitHub logo, taken from https://github.com/facebook/docusaurus/blob/master/website/src/css/custom.css */
39 |
40 | .header-github-link:hover {
41 | opacity: 0.6;
42 | }
43 |
44 | .header-github-link::before {
45 | content: "";
46 | width: 24px;
47 | height: 24px;
48 | display: flex;
49 | background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
50 | no-repeat;
51 | }
52 |
53 | [data-theme="dark"] .header-github-link::before {
54 | background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
55 | no-repeat;
56 | }
57 |
58 | /* get rid of pagination links at the bottom (seems there is no config option for this) */
59 |
60 | .pagination-nav {
61 | display: none;
62 | }
63 |
64 | /* custom elements */
65 |
66 | .embedded-fa-icon {
67 | max-width: 1em;
68 | max-height: 1em;
69 | position: relative;
70 | top: 0.125em;
71 | }
72 |
73 | html[data-theme="dark"] .embedded-fa-icon {
74 | fill: #f5f6f7;
75 | fill: var(--ifm-font-base-color);
76 | }
77 |
78 | a svg.embedded-fa-icon,
79 | html[data-theme="dark"] a svg.embedded-fa-icon {
80 | fill: #3578e5;
81 | fill: var(--ifm-link-color);
82 | }
83 |
84 | div.github-footer {
85 | margin-top: 60px;
86 | display: flex;
87 | flex-direction: row;
88 | justify-content: space-between;
89 | }
90 |
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/Boundaries-database.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: How architectural boundaries apply to the use of databases
3 | last_modified: 2020-11-21T18:14:37.148Z
4 | ---
5 |
6 | # Boundaries and the database
7 |
8 | ## Contents
9 |
10 | - [Boundaries between the domain and the database](#boundaries-between-the-domain-and-the-database)
11 | - [Separation at the database level](#separation-at-the-database-level)
12 | - [Resources](#resources)
13 |
14 | ## Boundaries between the domain and the database
15 |
16 | Typically makes sense to draw a boundary between the actual domain logic and the database (unless your application is a thin layer around the database that doesn’t really have any domain logic)
17 |
18 | One widespread convention: _Repository_ pattern:
19 |
20 | - All interaction with the database is encapsulated inside Repository classes
21 | - The domain logic interacts with these classes, without having to know anything database-specific
22 |
23 | ```java
24 | interface UserRepository {
25 | getUsers(): Promise;
26 | getUser(id: string): Promise;
27 | saveUser(user: User): Promise;
28 | deleteUser(id: string): Promise;
29 | }
30 |
31 | class SqlServerUserRepository implements UserRepository {
32 | // implement UserRepository methods by talking to SQL Server
33 | }
34 |
35 | class UserService {
36 | constructor(private repository: UserRepository) { }
37 |
38 | async updateName(id: string, newName: string) {
39 | const user = await this.repository.getUser(id);
40 | user.setName(newName);
41 | await this.repository.saveUser(user);
42 | }
43 | }
44 | ```
45 |
46 | If the domain logic is using the repository interface, then it also becomes easy to swap out the `SqlServerUserRepository` for a different implementation, for example an in-memory repository for testing purposes.
47 |
48 | ```java
49 | class InMemoryUserRepository implements UserRepository {
50 | // implement UserRepository methods using in-memory storage
51 | }
52 | ```
53 |
54 | The _Repository_ pattern also makes it easy to implement _caching_. Ideally, the repository takes care of caching values and invalidating the cache as needed, without other code even being aware that there is any caching at all.
55 |
56 | ## Separation at the database level
57 |
58 | For larger systems, it can make sense to separate different parts of the application down to the database level
59 |
60 | - Each part uses different tables or a different database
61 | - No direct links (like foreign keys) between data belonging to different parts
62 | - Considered good practice when setting up a microservices architecture
63 | - Sharing of database tables between services introduces tight coupling, potential data corruption in case of conflicting code between the services, ...
64 | - Can also do this in monolithic applications, potentially as a stepping stone towards a future microservices architecture
65 | - Easier to reason about separate parts of the application without having to think about other parts
66 | - More flexibility to change the schema or database technology for a certain part of the system
67 |
68 | When drawing boundaries down to the database level, some data that is relevant to two parts of the system might exist on both sides of the boundary between them
69 |
70 | See also [Microservices](../reference-architectures/Microservices.md), and specifically [Microservices - Data duplication and bounded contexts](../reference-architectures/Microservices.md#data-duplication-and-bounded-contexts)
71 |
72 | ## Resources
73 |
74 | - Clean Architecture (book by Robert C. Martin)
75 | - Building Evolutionary Architectures (book by Neal Ford, Rebecca Parsons and Patrick Kua) ([summary slides](http://nealford.com/downloads/Evolutionary_Architecture_Keynote_by_Neal_Ford.pdf))
76 |
--------------------------------------------------------------------------------
/web/css/Browser-compatibility.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Browser compatibility
3 | description: Making sure your CSS works in different browsers
4 | last_modified: 2022-01-27T17:10:03.020Z
5 | ---
6 |
7 | # Browser compatibility (CSS)
8 |
9 | ## Contents
10 |
11 | - [Eliminating inconsistencies](#eliminating-inconsistencies)
12 | - [Checking which browsers support certain functionality](#checking-which-browsers-support-certain-functionality)
13 | - [Support queries](#support-queries)
14 | - [Vendor prefixes](#vendor-prefixes)
15 | - [Polyfills](#polyfills)
16 | - [Testing in different browsers](#testing-in-different-browsers)
17 | - [Resources](#resources)
18 |
19 | ## Eliminating inconsistencies
20 |
21 | Problem: Different browsers use different defaults for how elements should look like
22 |
23 | Solution: **CSS reset** stylesheet that overrides browser defaults by some sensible values and provides a "clean slate" for your CSS to build upon
24 |
25 | Example: [Normalize.css](https://necolas.github.io/normalize.css/)
26 |
27 | ## Checking which browsers support certain functionality
28 |
29 | - Can use [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference)
30 | - Example: [compatibility for grid-template-columns](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns#Browser_compatibility)
31 | - Can use [Can I Use](https://caniuse.com/)
32 | - Example: [compatibility for grid-template-columns](https://caniuse.com/#feat=mdn-css_properties_grid-template-columns)
33 |
34 | ## Support queries
35 |
36 | Can be used to conditionally apply CSS only if the browser supports certain functionality
37 |
38 | Example:
39 |
40 | ```css
41 | @supports (display: grid) {
42 | .container {
43 | display: grid;
44 | /* other grid properties */
45 | }
46 | }
47 | ```
48 |
49 | ## Vendor prefixes
50 |
51 | Different browsers implement new features differently and at different speeds
52 |
53 | Vendor prefixes: browser-specific (or rendering-engine-specific) prefixes on properties or values that trigger a browser-specific (or rendering-engine-specific) version of the feature
54 |
55 | Goals:
56 |
57 | - Allow developers to make use of new features before they are standardized
58 | - When the features become standardized, it is still possible to get the old non-standard behaviors by using the prefixes (don't break behavior for early adopters that depend on some specific non-standard behavior)
59 | - By including the vendor prefixes next to the normal properties/values for a standardized feature, you can still support older browser versions in which the feature was not yet standardized
60 |
61 | Example:
62 |
63 | ```css
64 | .container {
65 | /* last one supported by current browser wins */
66 | display: -webkit-box;
67 | display: -ms-flexbox;
68 | display: -webkit-flex;
69 | display: flex;
70 | }
71 | ```
72 |
73 | You can also automatically include vendor prefixes by using a tool like [Autoprefixer](https://github.com/postcss/autoprefixer)
74 |
75 | ## Polyfills
76 |
77 | Polyfill = JavaScript that enables certain features in browsers that would not support them otherwise
78 |
79 | Can be useful, but polyfills come at a cost (loading + execution time)
80 |
81 | Also, it is pretty much impossible to create a CSS polyfill that is not either big, slow or doesn't behave the way it should in all cases. See [The Dark Side of Polyfilling CSS](https://philipwalton.com/articles/the-dark-side-of-polyfilling-css/).
82 |
83 | ## Testing in different browsers
84 |
85 | Useful tool: [BrowserStack](https://www.browserstack.com/) (or one of its many alternatives)
86 |
87 | ## Resources
88 |
89 | - [CSS - The Complete Guide 2020 (incl. Flexbox, Grid & Sass)](https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/)
90 | - [Supporting older browsers](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers)
91 |
--------------------------------------------------------------------------------
/javascript/typescript/Conditional-types.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Conditional types
3 | description: An explanation of TypeScript conditional types and an overview of some useful predefined ones
4 | last_modified: 2020-05-30T15:54:15+02:00
5 | ---
6 |
7 | # Conditional types (TypeScript)
8 |
9 | ## Contents
10 |
11 | - [Basic idea](#basic-idea)
12 | - [Predefined conditional types](#predefined-conditional-types)
13 | - [Resources](#resources)
14 |
15 | ## Basic idea
16 |
17 | Conditional type: selects one of two possible types based on a condition, where the condition is something that tests for the relationship between types
18 |
19 | General structure: `T extends U ? X : Y`
20 |
21 | Examples (adapted from [Conditional Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types)):
22 |
23 | ```typescript
24 | declare function f(x: T): T extends true ? string : number;
25 |
26 | let test1 = f(Math.random() < 0.5); // type: string | number
27 | let test2 = f(true); // type: string
28 | let test3 = f(false); // type: number;
29 | ```
30 |
31 | ```typescript
32 | type TypeName = T extends string
33 | ? "string"
34 | : T extends number
35 | ? "number"
36 | : T extends boolean
37 | ? "boolean"
38 | : T extends undefined
39 | ? "undefined"
40 | : T extends Function
41 | ? "function"
42 | : "object";
43 |
44 | type T0 = TypeName; // "string"
45 | type T1 = TypeName<"a">; // "string"
46 | type T2 = TypeName; // "boolean"
47 | type T3 = TypeName<() => void>; // "function"
48 | type T4 = TypeName; // "object"
49 | ```
50 |
51 | The above were examples where the conditional type is _resolved_ (the compiler can immediately decide what the resulting type is going to be)
52 |
53 | Alternatively, the type can be _deferred_, meaning the compiler will decide when it has more info
54 |
55 | Example (adapted from [Conditional Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types)):
56 |
57 | ```typescript
58 | interface Test {
59 | propA: boolean;
60 | propB: boolean;
61 | }
62 |
63 | declare function f(x: T): T extends Test ? string : number;
64 |
65 | // return type: T extends Test ? string : number
66 | function test(x: U) {
67 | return f(x); // type
68 | }
69 |
70 | const result1 = test("a") // type: number
71 | const result2 = test({ propA: true, propB: false }) // type: string
72 | ```
73 |
74 | ## Predefined conditional types
75 |
76 | Some conditional types already defined by the TypeScript language (see [Predefined conditional types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#predefined-conditional-types)):
77 |
78 | - `Exclude` — Exclude from `T` those types that are assignable to `U`
79 | - `Extract` — Extract from `T` those types that are assignable to `U`
80 | - `NonNullable` — Exclude `null` and `undefined` from `T`
81 | - `ReturnType` — Obtain the return type of a function type
82 | - `InstanceType` — Obtain the instance type of a constructor function type
83 |
84 | Examples (adapted from [Predefined conditional types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#predefined-conditional-types)):
85 |
86 | ```typescript
87 | type Test1 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
88 | type Test2 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
89 |
90 | type Test3 = Exclude void), Function>; // string | number
91 | type Test4 = Extract void), Function>; // () => void
92 |
93 | type Test5 = NonNullable; // string | number
94 | type Test6 = NonNullable<(string[] | null | undefined>; // string[]
95 |
96 | type Test7 = ReturnType<() => boolean> // boolean
97 | ```
98 |
99 | ## Resources
100 |
101 | - [Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
102 |
--------------------------------------------------------------------------------
/java/Optional.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Optional type
3 | description: How and when to use the Java Optional type
4 | last_modified: 2020-05-30T15:54:15+02:00
5 | ---
6 |
7 | # Optional type (Java)
8 |
9 | ## Contents
10 |
11 | - [Basic idea](#basic-idea)
12 | - [How to use Optional values](#how-to-use-optional-values)
13 | - [How not to use Optional values](#how-not-to-use-optional-values)
14 | - [Creating Optional values](#creating-optional-values)
15 | - [Turning an Optional into a Stream](#turning-an-optional-into-a-stream)
16 | - [Resources](#resources)
17 |
18 | ## Basic idea
19 |
20 | `Optional`: a wrapper for either an object of type `T` or no object
21 |
22 | Goal: provide safer alternative to returning either an object of type `T` or `null`
23 |
24 | Main use case: return type for methods that do not necessarily produce a value
25 |
26 | Note: Method parameters of type `Optional` are not recommended because this makes it awkward to call the method. For implementing methods with optional parameters, method overloading is generally considered a better option. See also [Why should Java 8's Optional not be used in arguments](https://stackoverflow.com/a/39005452)
27 |
28 | ## How to use Optional values
29 |
30 | Basically, two sensible options:
31 |
32 | - use a method that produces an alternative value if the Optional is empty
33 | - use a method that only consumes the value if the Optional is not empty
34 |
35 | Examples first option:
36 |
37 | ```java
38 | String result = optionalString.orElse("");
39 | String result = optionalString.orElseGet(functionReturningString);
40 | String result = optionalString.orElseThrow(IllegalStateException::new);
41 | ```
42 |
43 | Examples second option:
44 |
45 | ```java
46 | optionalString.ifPresent(processString); // returns nothing
47 |
48 | optionalString.ifPresentOrElse(
49 | System.out::println,
50 | () -> System.out.println("Empty!")); // returns nothing
51 |
52 | // Optional containing the length of the value (if it was present) and empty otherwise
53 | optionalString.map(String::length)
54 |
55 | optionalString.flatMap(functionReturningOptionalInteger) // Optional
56 | ```
57 |
58 | ## How not to use Optional values
59 |
60 | When used in the wrong way, using `Optional` is not safer or easier than using null
61 |
62 | Examples:
63 |
64 | ```java
65 | nullableString.length() // length throws NullPointerException
66 | optionalString.get().length() // get throws NoSuchElementException
67 |
68 | if (nullableString != null) {
69 | length = nullableString.length()
70 | }
71 |
72 | if (optionalString.isPresent()) {
73 | length = optionalString.get().length()
74 | }
75 | ```
76 |
77 | ## Creating Optional values
78 |
79 | ```java
80 | Optional optionalString = Optional.of("test"); // throws if argument null
81 | Optional optionalString = Optional.ofNullable(nullableString);
82 | Optional optionalString = Optional.empty();
83 | ```
84 |
85 | ## Turning an Optional into a Stream
86 |
87 | Conceptually, you can compare an Optional to a stream with either zero or one elements. The `.stream()` method follows that principle, yielding a stream with zero elements if the Optional is empty and a stream with one element if the optional has a value
88 |
89 | Example use case:
90 |
91 | ```java
92 | idsStream
93 | .map(Users::lookup) // Users.lookUp returns an Optional
94 | .flatMap(Optional::stream)
95 | ```
96 |
97 | Note: if you call a method that returns either a value or null, you can apply the samle principle using `Stream.ofNullable`:
98 |
99 | ```java
100 | idsStream
101 | .map(Users::lookup) // Users.lookUp returns a User object or null
102 | .flatMap(Stream::ofNullable)
103 | ```
104 |
105 | ## Resources
106 |
107 | - Core Java SE 9 for the Impatient (book by Cay S. Horstmann)
108 | - [Why should Java 8's Optional not be used in arguments](https://stackoverflow.com/a/39005452)
109 |
--------------------------------------------------------------------------------
/web/css/Flexbox.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Flexbox
3 | description: The main idea of CSS Flexbox
4 | last_modified: 2022-01-31T10:44:35.361Z
5 | ---
6 |
7 | # Flexbox (CSS)
8 |
9 | ## Contents
10 |
11 | - [Basic idea](#basic-idea)
12 | - [Sizing of flex items](#sizing-of-flex-items)
13 | - [Alignment of flex items](#alignment-of-flex-items)
14 | - [Wrapping](#wrapping)
15 | - [Use cases](#use-cases)
16 | - [Resources](#resources)
17 |
18 | ## Basic idea
19 |
20 | 
21 |
22 | ([image source](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox))
23 |
24 | - **Flex container** = parent element with `display: flex`
25 | - Children of container = **flex items** (their size and position is determined by flexbox)
26 | - **Main axis** = direction in which the chldren of the container are laid out
27 | - Horizontal if container has `flex-direction: row;`
28 | - Vertical if container has `flex-direction: column;`
29 | - **Cross axis** = direction perpendicular to main axis
30 | - Note: Flexbox is mainly suitable when you want your items to adjust their sizes to their container along a single direction (either horizontally or vertically). If both horizontal and vertical sizing is important to you, [Grids](./Grids.md) may be a better option.
31 |
32 | ## Sizing of flex items
33 |
34 | You can control the sizing of flex items along the main axis by setting their `flex` property (see [flex](https://developer.mozilla.org/en-US/docs/Web/CSS/flex) for a bit more details)
35 |
36 | The `flex` property can have up to 3 values:
37 |
38 | - Flex grow: a unitless proportion that indicates the extent to which the item will grow with its container
39 | - Flex shrink: a unitless proportion that indicates the extent to which the item will shrink (if needed) to fit the container
40 | - Flex basis: the minimum size of the item
41 |
42 | ## Alignment of flex items
43 |
44 | Alignment along the main axis: [justify-content](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content) (set at the level of the container)
45 |
46 | - `flex-start` (default): make items sit towards the start of the main axis
47 | - `flex-end`: make items sit towards the endof the main axis
48 | - `center`: make items sit towards the center of the main axis
49 | - `space-around`: evenly distribute items (same amount of spacing between adjacent items) and leave half of that spacing at the start and end of the main axis
50 | - `space-between`: evenly distribute items (same amount of spacing between adjacent items), without any spacing at the start and end of the main axis
51 | - Simple use case: two elements, one sticking to the left side of the container and one sticking to the right side of the container
52 |
53 | Alingment along the cross axis: [align-items](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items) (set at the level of the container, can override at the item level using [align-self](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self))
54 |
55 | - `stretch` (default): make items fill the parent along the cross axis
56 | - `center`: center items along the cross axis
57 | - `flex-start` or `flex-end`: start or end of cross axis
58 |
59 | ## Wrapping
60 |
61 | You can make your items wrap to a new row/column as necessary using `flex-wrap: wrap;` on the container
62 |
63 | ## Use cases
64 |
65 | Some use cases for Flexbox:
66 |
67 | - Vertical centering
68 | - Sticky footer (sticks to bottom of screen if content doesn't fill screen)
69 | - Make an element take up all of the vertical space that is not yet taken up by other elements
70 | - Make the children of a container scale along with the size of the container
71 | - Show the children of a container side-by-side and make them have the same height, even if their content doesn't take up the same height
72 |
73 | ## Resources
74 |
75 | - [CSS - The Complete Guide 2020 (incl. Flexbox, Grid & Sass)](https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/)
76 | - [Flexbox](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox)
77 | - [flex](https://developer.mozilla.org/en-US/docs/Web/CSS/flex)
78 | - [Solved by Flexbox](https://philipwalton.github.io/solved-by-flexbox/)
79 |
--------------------------------------------------------------------------------
/architecture-design/architectural-boundaries-details/Boundaries-third-party-dependencies.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Why it's important to create boundaries around your dependencies
3 | last_modified: 2021-01-03T11:43:26.271Z
4 | ---
5 |
6 | # Boundaries and third-party dependencies
7 |
8 | ## Contents
9 |
10 | - [Main idea](#main-idea)
11 | - [Boundaries around dependencies](#boundaries-around-dependencies)
12 | - [Be extra careful with frameworks](#be-extra-careful-with-frameworks)
13 | - [Resources](#resources)
14 |
15 | ## Main idea
16 |
17 | Take care not to let too much of your code depend on third-party code!
18 |
19 | - External dependencies evolve in a way you do not control
20 | - Their newest version including some critical bugfixes may introduce breaking changes in an API you use or even remove the functionality you use
21 | - They may stop being properly maintained
22 | - Your own requirements relevant to the dependency may change
23 | - All of this can force you to change the way you use the dependency or even replace it with another dependency
24 |
25 | ## Boundaries around dependencies
26 |
27 | Consider creating a boundary around the external dependency that decouples the rest of the system from it (this boundary is sometimes called an _Anti-Corruption Layer_):
28 |
29 | - The public interface of that boundary should be written in terms of what your system needs from the dependency
30 | - Logic inside the boundary will be specific to the interaction with that particular dependency.
31 | - This also applies when the external dependency is another system!
32 | - In that case, it often makes sense to set up some kind of validation for the responses from that system
33 |
34 | Benefits:
35 |
36 | - If the API of the dependency changes or you replace it, the boundary protects you from having to change all code that used the dependency. As long as you can fulfill the contract specified by the public interface of the boundary, no code outside of the boundary has to be aware of the change.
37 | - Especially useful if you consider the dependency to be a temporary solution that is sufficient for now but will most likely need to change in the future. The boundary allows you to avoid premature complexity by going for a simple solution, while keeping your options open regarding the upgrade to a more complex solution.
38 | - You can also use the boundary to create some automated tests for the specific functionality that your system needs to get from the boundary. By testing against the boundary, you don’t have to change your tests in order to be able to test a new version of the dependency or even a replacement.
39 |
40 | ## Be extra careful with frameworks
41 |
42 | - Frameworks tend to dictate the structure of your application and may even ask you to base your domain objects on the abstractions they provide. If you allow this, it will be very difficult to get the framework out afterwards.
43 | - An opinionated framework dictating the structure of your application can also be a good thing, allowing team to focus on building functionality rather than discussing the ideal structure
44 | - For more flexibility, it can help to let the framework operate on some kind of separate representation of your domain objects instead of the domain objects themselves. Your boundary could then take care of performing the necessary translations between that separate representation and the actual domain objects.
45 | - Can require a lot of overhead in terms of additional classes, getting data in and out of DTOs to pass between layers, taking care of things that your framework would normally automatically take care of, ...
46 | - Might not be worth it!
47 | - Tightly integrating a framework into your application should be a conscious and well-motivated decision
48 |
49 | ## Resources
50 |
51 | - Clean Architecture (book by Robert C. Martin)
52 | - Building Evolutionary Architectures (book by Neal Ford, Rebecca Parsons and Patrick Kua) ([summary slides](http://nealford.com/downloads/Evolutionary_Architecture_Keynote_by_Neal_Ford.pdf))
53 | - [Our Software Dependency Problem](https://research.swtch.com/deps)
54 | - [Is it common practice to validate responses from 3rd party APIs?](https://softwareengineering.stackexchange.com/questions/410248/is-it-common-practice-to-validate-responses-from-3rd-party-apis)
55 |
--------------------------------------------------------------------------------
/architecture-design/Humble-Object-pattern.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Separating hard-to-test and easy-to-test behavior
3 | last_modified: 2022-01-28T10:14:49.276Z
4 | ---
5 |
6 | # Humble Object pattern
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Values as boundaries](#values-as-boundaries)
12 | - [Resources](#resources)
13 |
14 | ## Basic idea
15 |
16 | - Problem: some behavior (like how data is represented on a screen) is hard to test
17 | - Solution: split the behavior into two parts
18 | - Humble Object containing the hard-to-test stuff, stripped down to the bare essence
19 | - Other, easily testable part which contains everything stripped from the Humble Object
20 |
21 | Example: showing data in a UI
22 |
23 | - Create a view model that describes as much as possible about how the data will be shown
24 | - Dates already converted to correct format
25 | - Flags describing if elements should be disabled, hidden, ...
26 | - Humble Object is a view which does nothing more than showing contents of view model on the screen
27 |
28 | ## Values as boundaries
29 |
30 | (also called "Functional Core, Imperative Shell")
31 |
32 | See this talk: [Boundaries](https://www.destroyallsoftware.com/talks/boundaries) (some more details [here](https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell))
33 |
34 | Same idea as Humble Object pattern, but taken to a more architectural level:
35 |
36 | - Functional Core: all decision logic sits here, no mutation, input and output are just values (see below)
37 | - Pure functions: output depends on input only, not on some other kind of state
38 | - Very easy and efficient to unit test
39 | - Imperative Shell: layer around the core, holds dependencies, takes care of interaction with the outside world (DB, web, screen, keyboard, ...)
40 | - Contains the slow code that can fail
41 | - Hard to test, but there shouldn't be much to test (a few integration or end-to-end tests should give you all the confidence you need)
42 | - Straightforward mapping between values returned from core and the effect on DB/screen/...
43 | - Core could return a complete representation of the new state, or some representation of changes to be made on top of the previous state (print a line on screen, perform a specific update on a specific DB row, ...)
44 | - System can consist of multiple shells (each with their own core) that communicate with each other
45 |
46 | The definition of a _value_ in this context: anything immutable
47 |
48 | - Could be a simple integer
49 | - Could be an object with immutable state, plus methods whose result depends on that state (and thus doesn't change either)
50 | - Every mutating operation should return a new object rather than mutating an existing object's state
51 | - Example: Java's String class
52 |
53 | Additional benefit of these values (in addition to testability): values like these are easy to pass as messages. This way, values can be used as boundaries between classes, subsystems, processes and even different machines.
54 |
55 | Some limitations to this "values as boundaries" approach:
56 |
57 | - Doesn't make sense for systems where the main complexity sits in the interaction with the outside world (this would leave us with a core that's more or less empty)
58 | - Challenging if the business logic requires a lot of back-and-forth with a DB or similar
59 | - "To perform action A, we need to retrieve X, then based on X we decide what Y to retrieve, and then we calculate how to update some Z based on X and Y"
60 | - If we extract the `X->'what Y to retrieve'` and `X,Y->'which Z to update in which way'` logic to the core (because that is the decision logic), it becomes harder to get the full picture of the business logic because it is split across multiple core functions that are tied together by the imperative shell
61 | - You can imagine this gets worse and worse when more back-and-forth is needed
62 |
63 | ## Resources
64 |
65 | - Clean Architecture (book by Robert C. Martin)
66 | - [TDD Patterns: Humble Object](https://ieftimov.com/post/tdd-humble-object/)
67 | - [Dry running a function](https://softwareengineering.stackexchange.com/questions/436257/dry-running-a-function) ([relevant answer](https://softwareengineering.stackexchange.com/a/436259))
68 |
--------------------------------------------------------------------------------
/processes-techniques/testing-details/Testing-after-production.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Why testing in production (rather than before deploying) could make sense in some cases
3 | last_modified: 2022-01-02T14:25:32.148Z
4 | ---
5 |
6 | # Testing after production
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Mean time between failures versus mean time to repair](#mean-time-between-failures-versus-mean-time-to-repair)
12 | - [Separating deployment from release](#separating-deployment-from-release)
13 | - [Monitoring and logging](#monitoring-and-logging)
14 | - [Synthetic monitoring](#synthetic-monitoring)
15 | - [Resources](#resources)
16 |
17 | ## Basic idea
18 |
19 | - Tests will never be perfect, we can't catch everything! Impossible to reduce chance of failure to zero
20 | - It might be impractical and not worth the effort to test certain things before putting them in production
21 |
22 | ## Mean time between failures versus mean time to repair
23 |
24 | - Mean time between failures (MTBF): indication of how often issues make it to production
25 | - Mean time to repair (MTTR): indication of how long it takes you to detect and fix such issues
26 |
27 | Tradeoff MTBF versus MTTR:
28 |
29 | - Sometimes, it's more efficient to spend effort on getting better at detecting and fixing issues in production than on adding more automated tests
30 | - Best tradeoff depends on your organization
31 | - Do not completely abandon one in favor of the other
32 | - It's probably not a good idea to just throw stuff into production without any level of testing
33 | - Even with great tests, you need to be prepared for a bug popping up in production
34 |
35 | ## Separating deployment from release
36 |
37 | Basic idea: after deploying something, don't immediately direct full production load to it
38 |
39 | Useful techniques:
40 |
41 | - **Smoke tests**:
42 | - Tests designed to check that deployment was successful and software runs properly in current environment
43 | - Should ideally be run automatically on deploy
44 | - **Blue/green deployment**:
45 | - Run old and new next to each other
46 | - New can get smoke tested while old still handles production load, then we can switch
47 | - After switching to new, we can quickly switch back if necessary
48 | - **Canary releasing**:
49 | - Keep old and new next to each other for longer time
50 | - Only direct a fraction of production load to new, increase as confidence increases
51 | - **Branch By Abstraction** and **application strangulation** (see [Branch By Abstraction and application strangulation](../Branch-by-abstraction-application-strangulation.md)):
52 | - Techniques to gradually migrate to new code or even new system
53 | - Possible to direct production traffic to existing code/system but also send a copy of it to new code/system to check for differences in behavior
54 |
55 | ## Monitoring and logging
56 |
57 | - Monitor CPU, memory, ...
58 | - Monitor application itself: response time, number of errors returned to client, number of submitted forms, ...
59 | - Collect logs about what the system is doing
60 | - It's especially important to log any errors that happen
61 | - Set up dashboards so people can quickly get an idea of the system's state
62 | - Set up alerts based on resource use, response time, error rates, 500 responses, ...
63 | - Alert early enough so team can act before things really get bad
64 | - Watch your signal-to-noise ratio, so people don't start ignoring alerts
65 |
66 | ## Synthetic monitoring
67 |
68 | (also called **semantic monitoring**)
69 |
70 | Basic idea: monitor health of system as whole by running end-to-end scenarios against it
71 |
72 | Approach:
73 |
74 | - Define important scenarios or user journeys
75 | - Write tests for them (often make sense to start from end-to-end tests)
76 | - Periodically run these against production
77 | - Depending on importance of scenario or journey, failure can trigger on-call alert
78 |
79 | Benefits/challenges:
80 |
81 | - Often way better at finding out if something's wrong than lower-level metrics
82 | - Still, you'll likely need lower-level metrics to help you find the exact location of the issue
83 | - Make sure it doesn't affect actual production customers!
84 |
85 | ## Resources
86 |
87 | - Martin Fowler's [Software Testing Guide](https://martinfowler.com/testing/):
88 | - [QA in Production](https://martinfowler.com/articles/qa-in-production.html)
89 | - [Synthetic Monitoring](https://martinfowler.com/bliki/SyntheticMonitoring.html)
90 | - Building Microservices (book by Sam Newman)
91 |
--------------------------------------------------------------------------------
/web/css/Naming-classes.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Naming classes
3 | description: Some ideas/patterns for naming your CSS classes
4 | last_modified: 2020-11-28T16:32:04.296Z
5 | ---
6 |
7 | # Naming classes (CSS)
8 |
9 | ## Contents
10 |
11 | - [Some general tips](#some-general-tips)
12 | - [Object Oriented CSS](#object-oriented-css)
13 | - [Block Element Modifier (BEM)](#block-element-modifier-bem)
14 | - [Resources](#resources)
15 |
16 | ## Some general tips
17 |
18 | - Use `snake-case`
19 | - Name classes by feature (example: `.page-title`) instead of style (example: `.title-blue`)
20 | - One reason: if name your class by style and you want to change something about the style, you would need to change the class name and change the HTML accordingly everywhere it's used
21 | - Note: CSS frameworks often have utility classes that are named by style (`.visibility-hidden`, `.text-center`, ...).
22 | - Note: There are frameworks like [Tailwind CSS](https://tailwindcss.com/) that pretty much rely completely on utility classes that are named after the style they apply. For the philosophy behind this and some drawbacks of the rest of the advice in this note, see [CSS Utility Classes and "Separation of Concerns"](https://adamwathan.me/css-utility-classes-and-separation-of-concerns/).
23 | - Don't go too specific: instead of creating very specific classes (or selector) that have a lot of duplication between them, try to encapsulate different parts of the behavior you want into classes that you can then combine
24 | - Example: instead of `.main-article-box` or `article.main p.box`, consider going for `.box` which you can apply in different places, potentially combined with other classes
25 |
26 | ## Object Oriented CSS
27 |
28 | - Idea: separate CSS into reusable "objects" that can be used anywhere you need
29 | - The way people use CSS today is heavily influenced by this approach
30 |
31 | Example CSS not using OOCSS approach:
32 |
33 | ```css
34 | .comment {
35 | display: grid;
36 | grid-template-columns: 1fr 3fr;
37 | }
38 |
39 | .comment img {
40 | border: 1px solid grey;
41 | }
42 |
43 | .comment .content {
44 | font-size: .8rem;
45 | }
46 |
47 | .list-item {
48 | display: grid;
49 | grid-template-columns: 1fr 3fr;
50 | border-bottom: 1px solid grey;
51 | }
52 |
53 | .list-item .content {
54 | font-size: .8rem;
55 | }
56 | ```
57 |
58 | Example CSS using OOCSS approach:
59 |
60 | ```css
61 | .media {
62 | display: grid;
63 | grid-template-columns: 1fr 3fr;
64 | }
65 |
66 | .media .content {
67 | font-size: .8rem;
68 | }
69 |
70 | .comment img {
71 | border: 1px solid grey;
72 | }
73 |
74 | .list-item {
75 | border-bottom: 1px solid grey;
76 | }
77 | ```
78 |
79 | Example HTML for comment:
80 |
81 | ```html
82 |
83 |
84 |
85 |
86 | ```
87 |
88 | Example HTML for list item:
89 |
90 | ```html
91 |
92 |
93 |
94 |
95 |
96 |
97 | ```
98 |
99 | ## Block Element Modifier (BEM)
100 |
101 | - Naming standard for CSS classes
102 | - Terminology:
103 | - Block: button, menu, logo, ...
104 | - Element: something in the block
105 | - Modifier: a flag that changes style or behavior
106 | - Class names: `block__element--modifier`
107 | - Typical use case: large web projects
108 | - Can be overkill for smaller projects or for projects that have a way of making CSS more modular by making specific pieces of CSS only apply to specific parts of the website (example: [Angular component styles](https://angular.io/guide/component-styles))
109 |
110 | BEM example (from [Get BEM](http://getbem.com/naming/)):
111 |
112 | ```html
113 |
119 | ```
120 |
121 | ```css
122 | .form { }
123 | .form--theme-xmas { }
124 | .form--simple { }
125 | .form__input { }
126 | .form__submit { }
127 | .form__submit--disabled { }
128 | ```
129 |
130 | ## Resources
131 |
132 | - [CSS - The Complete Guide 2020 (incl. Flexbox, Grid & Sass)](https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/)
133 | - [Organizing your CSS](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Organizing)
134 | - [CSS Utility Classes and "Separation of Concerns"](https://adamwathan.me/css-utility-classes-and-separation-of-concerns/)
135 |
--------------------------------------------------------------------------------
/architecture-design/oo-design/Avoiding-fat-service-classes.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Some ways to avoid service classes getting bigger and bigger
3 | last_modified: 2020-06-13T13:29:49+02:00
4 | ---
5 |
6 | # Avoiding fat service classes
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Approach: split into sub-services](#approach-split-into-sub-services)
12 | - [Approach: delegate to focused classes](#approach-delegate-to-focused-classes)
13 | - [Resources](#resources)
14 |
15 | ## Basic idea
16 |
17 | - In a lot of applications, you have service classes that act as a facade for lower-level domain logic and also contain coordination and control logic
18 | - These service classes tend to grow over time and can become so "fat" that they are difficult to maintain
19 |
20 | ## Approach: split into sub-services
21 |
22 | Basic idea:
23 |
24 | - Identify different areas of functionality within the fat service class
25 | - Potential way to split: identify sub-concepts
26 | - Potential way to split: retrieval of data vs. changing data
27 | - Create a separate service for each area
28 | - If needed, you can create a helper service for sharing common functionality
29 | - Either the old fat service class acts as a facade to these more specific service classes, or clients call the sub-services directly
30 |
31 | ## Approach: delegate to focused classes
32 |
33 | Basic idea:
34 |
35 | - Identify the actions that the fat service class is performing
36 | - This could be as simple as "1 public method = 1 action"
37 | - Create a separate class to represent each action
38 | - It might make sense to have all of these actions implement a common interface, especially if there are some "cross-cutting concerns" that need to be taken care of regardless of the specific type of action
39 | - The old fat service class creates the actions and then delegates to them
40 | - Typically each call to the fat service class will create one or more instances of the action classes based on the specific input received
41 | - The old fat service class takes care of cross-cutting concerns if needed
42 |
43 | This can be seen as a form of the [Command pattern](https://en.wikipedia.org/wiki/Command_pattern)
44 |
45 | Benefits:
46 |
47 | - Class per action means that we get some very focused classes
48 | - Class per action means we can easily compose higher-level actions out of lower-level actions
49 | - This approach makes it relatively easy to provide undo functionality or show a history of actions (if needed)
50 |
51 | Example: virtual file system
52 |
53 | - Situation:
54 | - Fat service class with functionality for file creation, file update, file deletion, replacing a folder's contents with contents from an archive, ...
55 | - For every call to the service class, all changes must happen within a single DB transaction
56 | - All changes generate events that other components can listen to, plus they generate updates to an in-memory representation of the current state of the file system. However, those events and updates are only valid once the entire transaction is committed.
57 | - Solution:
58 | - Each file action (create, update, delete, ...) is implemented as its own class
59 | - All of these file action classes share the same interface, which specifies that they return events and in-memory cache updates
60 | - Bigger actions (archive import etc.) delegate work to smaller actions that they create
61 | - For every call to the service class, it creates the necessary actions based on the received input and also passes a transactional DB connection on construction
62 | - Service class collects event and cache updates
63 | - When all actions for a service class call have completed, the service class commits the DB transaction, sends events and applies updates to the in-memory file system representation
64 | - In this particular case, file actions depended on several lower-level services. Solution: file action factory service with methods for creating each type of action. Each method takes action input + DB connection and calls the action's constructor with action input, DB connection and instances of lower level services.
65 |
66 | ```typescript
67 | export interface FileAction {
68 | public executeAndGetResult(): Promise;
69 | }
70 |
71 | export interface FileActionResult {
72 | events: FileEvent[];
73 | cacheUpdates: FileCacheUpdate[];
74 | }
75 | ```
76 |
77 | ## Resources
78 |
79 | - [Service layer - fat service classes?](https://softwareengineering.stackexchange.com/questions/269544/service-layer-fat-service-classes)
80 | - [Command pattern](https://en.wikipedia.org/wiki/Command_pattern)
81 |
--------------------------------------------------------------------------------
/architecture-design/reference-architectures/Package-by-feature-or-component.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: A way to divide your system based on functional areas
3 | last_modified: 2024-11-17T18:47:03.774Z
4 | ---
5 |
6 | # Package by feature or component
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Benefits/drawbacks](#benefitsdrawbacks)
12 | - [Testing](#testing)
13 | - [Resources](#resources)
14 |
15 | ## Basic idea
16 |
17 | 
18 |
19 | 
20 |
21 | ([image source](http://www.codingthearchitecture.com/2015/03/08/package_by_component_and_architecturally_aligned_testing.html))
22 |
23 | - Divide system into features/components based on functional areas
24 | - A feature/component exposes an interface for the outside world to use and hides its internals (including DB access etc.) from the rest of the codebase
25 | - In package by feature, features are separated up to the level of controllers
26 | - If one feature needs another, it needs to go through the controller
27 | - In package by component, the separation happens below the level of controllers
28 | - If one component needs to call another, there is no need to go through controllers
29 | - Controllers can group and combine data based on what makes sense to API consumers
30 | - A single controller can easily use several components (could be especially handy for retrieving data)
31 | - A single component could be used by several controllers
32 | - The way components are divided into functional areas could potentially differ from the way controllers are divided into functional areas
33 | - Encapsulation of internals should be enforced
34 | - Ideally, use language constructs like packages, modules, ...
35 | - Alternatively, set up custom checks using static analysis. See [Static analysis - Internal dependencies](../../processes-techniques/Static-analysis.md#internal-dependencies).
36 | - Top-level structure shows functional areas of the application rather than technical layers
37 | - Within feature/component, likely to have some kind of layered structure, may or may not be the same across all features/components
38 |
39 | Note: probably still some cross-cutting concerns that apply to several features/components
40 |
41 | - Can just put these next to the features/components structure
42 | - Not all code has to be divided into features/components
43 |
44 | ## Benefits/drawbacks
45 |
46 | - Good way to divide codebase into different functional areas that different teams could potentially take ownership of
47 | - "Modular monolith"
48 | - Can be a good stepping stone towards microservices
49 | - Finding a sensible way to divide the system into clearly separated features/components could be challenging or feel artificial for some applications
50 |
51 | ## Testing
52 |
53 | - Some classes should be tested in isolation
54 | - Think domain classes, utility classes, ...
55 | - If large amount of mocking needed to test a class in isolation, it's maybe better to test it at another level
56 | - Some behavior easiest to test through public interface of feature/component
57 | - Treat feature/component as black box
58 | - Can still be useful to mock other components or external services when doing this
59 |
60 | The "reshaped testing pyramid" by Simon Brown (aimed at package by component or microservices):
61 |
62 | 
63 |
64 | ([image source](http://www.codingthearchitecture.com/2015/03/08/package_by_component_and_architecturally_aligned_testing.html))
65 |
66 | ## Resources
67 |
68 | - [Package by Feature Is Demanded](https://dzone.com/articles/package-by-feature-is-demanded)
69 | - [Package by component and architecturally-aligned testing](http://www.codingthearchitecture.com/2015/03/08/package_by_component_and_architecturally_aligned_testing.html)
70 | - Building Evolutionary Architectures (book by Neal Ford, Rebecca Parsons and Patrick Kua) ([summary slides](http://nealford.com/downloads/Evolutionary_Architecture_Keynote_by_Neal_Ford.pdf))
71 | - [Deconstructing the Monolith: Designing Software that Maximizes Developer Productivity](https://web.archive.org/web/20240327233505/https://shopify.engineering/deconstructing-monolith-designing-software-maximizes-developer-productivity)
72 | - [Cross-cutting concerns in package-by-feature structure](https://softwareengineering.stackexchange.com/questions/379563/cross-cutting-concerns-in-package-by-feature-structure)
73 |
--------------------------------------------------------------------------------
/web/Cookies-web-storage.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: What are Cookies and Web Storage? What do they have in common? What are their differences?
3 | last_modified: 2022-01-31T10:44:35.355Z
4 | ---
5 |
6 | # Cookies and Web Storage
7 |
8 | ## Contents
9 |
10 | - [What they have in common](#what-they-have-in-common)
11 | - [Cookies](#cookies)
12 | - [Web Storage](#web-storage)
13 | - [Resources](#resources)
14 |
15 | ## What they have in common
16 |
17 | - Solution for storing data client-side
18 | - Function as a kind of key-value store, allowing to store string values
19 |
20 | ## Cookies
21 |
22 | - Are typically set from the server (as part of a response to the client) using `Set-Cookie` headers
23 | - Are sent automatically as `Cookie` headers with each request to a domain and path matching the cookie's specified `Domain` and `Path`
24 | - Good for information that needs to be sent to the server on each call (for example tokens)
25 | - Can be particularly handy in cases where it's hard to control the actual request made to the server (examples: GET request from and `` tag, server-side rendering where each navigation loads a new page from the server, ...)
26 | - Not good for storing large amounts of data that don't need to be sent every time
27 | - Lifetime:
28 | - Session cookies: no specified expiry date or max age. Normally lasts until the browser is shut down, although browsers may use _session restoring_ which means they survive across browser restarts
29 | - Permanent cookies: specific expiry date (specified through `Expires`) or max age (specified through `Max-Age`)
30 | - `Secure` flag, if turned on the cookie can only be sent over HTTPS
31 | - `HttpOnly` flag, if turned on the cookie cannot be accessed by JavaScript
32 | - Recommended for storing sensitive information like tokens, as this helps prevent tokens from being stolen through XSS (cross-site scripting)
33 | - Cookies without this flag can be read/written by JavaScript (but only from JavaScript that was loaded by a page in a matching domain)
34 | - Cookies with the flag turned on can still be viewed and edited by the user, for example through developer tools!
35 | - Risk of CSRF (cross-site request forgery attacks), where a completely different site makes a request to your backend, counting on the fact that cookies holding tokens will automatically be sent
36 | - Can be mitigated by also requiring a CSRF token to be sent in a way that requires JavaScript being involved. An example is requiring the client to get the token from a cookie and then put it in a header (remember that cookies for a certain domain can only be accessed by JavaScript loaded by pages in that domain).
37 |
38 | ## Web Storage
39 |
40 | - Can be set and read from JavaScript loaded by a page with matching origin (origin = `protocol://host:port`)
41 | - Values don't get sent to the server unless JavaScript adds it to a request
42 | - Ideal for storing preferences, scores, ... that don't need to be stored on the server (or should be able to survive page reloads without asking the server for them again)
43 | - Can generally store more data than cookies (something along the lines of 5MB in total per domain, versus 4KB per cookie)
44 | - Lifetime:
45 | - `sessionStorage`: keeps the data as long as the page is open
46 | - Survives page reloads and restores
47 | - Opening the page in a new tab or window gives it its own separate `sessionStorage`
48 | - In some browsers, duplicating a tab gives the new tab its own separate `sessionStorage`, but the data from the original tab's `sessionStorage` is initially copied into it
49 | - `localStorage`: stays until cleared through JavaScript or the user clearing browser data
50 | - Interesting feature: `StorageEvent` fired when storage is changed, could be used within your web application to trigger certain things or even as a mechanism to communicate between different instances of your web application (in different windows or tabs) within the same browser
51 |
52 | ## Resources
53 |
54 | - [HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
55 | - [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API)
56 | - [What is the difference between localStorage, sessionStorage, session and cookies?](https://stackoverflow.com/questions/19867599/what-is-the-difference-between-localstorage-sessionstorage-session-and-cookies)
57 | - [Could someone explain the life of a sessionStorage object?](https://stackoverflow.com/questions/8945744/could-someone-explain-the-life-of-a-sessionstorage-object)
58 | - [In HTML5, is the localStorage object isolated per page/domain?](https://stackoverflow.com/questions/4201239/in-html5-is-the-localstorage-object-isolated-per-page-domain)
59 |
--------------------------------------------------------------------------------
/processes-techniques/Small-commits-pull-requests.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Why you should strive to commit early, push often and keep pull requests small
3 | last_modified: 2024-04-15T12:47:30.733Z
4 | ---
5 |
6 | # Small commits and pull requests
7 |
8 | ## Contents
9 |
10 | - [Small, atomic commits](#small-atomic-commits)
11 | - [Frequent pushes](#frequent-pushes)
12 | - [Small pull requests](#small-pull-requests)
13 | - [Resources](#resources)
14 |
15 | ## Small, atomic commits
16 |
17 | - Commits should be "atomic": a single commit should be dedicated to a single (sub)task
18 | - Separate commits for refactoring, bug fixes and new features
19 | - Avoid batching multiple kinds of changes together in a single commit
20 | - Each commit should represent one step forward in your process of solving the bug or implementing the feature
21 | - A commit represents a small incremental change to the codebase
22 | - Still likely to touch multiple files
23 | - Each commit should leave the codebase in a valid state
24 | - Tests should pass, the system should build properly, ...
25 | - Ideally, the commit also includes new tests relevant to the commit
26 | - Avoid committing throwaway code, commented-out code, `TODO` comments, ...
27 | - These make commit history harder to understand and PRs harder to review
28 |
29 | Approach:
30 |
31 | - Divide your work into small subtasks (30-60 minutes is ideal, more than 4 hours is probably too long)
32 | - Added benefit: this is a great way to fight procrastination and also makes it easier to context switch if needed
33 | - Work only on one subtask at a time and commit your changes once you have finished a subtask (taking care to leave the codebase in a valid state)
34 | - If you see the need for refactoring of fixes in the code you need to touch, try to put these in separate commits (either before or after you make your main changes)
35 | - If you are about to make a change which should be a separate commit (dependency install, refactor, …) you can stash your current changes to start from a clean slate and make that change as one logical commit. Then, you can restore the stash and continue.
36 | - If you already have a whole bunch of uncommitted changes that should ideally be split into multiple commits, you can stage specific files or even specific lines inside files to commit them separately
37 | - Can work fine as long as different logical changes don't touch the same code
38 |
39 | Benefits:
40 |
41 | - Focused commits make it easier to also provide focused commit messages
42 | - Easy to undo or revert a specific change
43 | - It's hard to throw away one specific change if it's mixed with a bunch of other changes to the same set of files
44 | - Makes pull request reviews easier
45 | - Reviewers can choose their view (total diff versus looking at separate commits)
46 | - Commit log a clear story of how you tackled the problem
47 |
48 | ## Frequent pushes
49 |
50 | - When you make your small, atomic commits, also push them to a remote repository
51 | - "Commit Early, Push Often"
52 |
53 | Benefits:
54 |
55 | - Pushing your work to a remote repository prevents you from losing your work due to disk failures or even brain farts
56 | - Pushing your commits as you make them provides transparency into your process
57 | - Gives your colleagues an idea of how far you are
58 | - Sometimes, your colleagues might be able to give you some early feedback or tips, potentially saving hours or even days of wasted work
59 |
60 | ## Small pull requests
61 |
62 | - Keep pull requests small and focused
63 | - Reviewers should be able to keep the entire pull request in their head when analyzing the code
64 | - As a reviewer, it should take you minutes rather than hours to review a pull request
65 | - It can help to split up issues/tasks into smaller ones
66 | - It can help to create a sequence of pull requests for one bigger issue/task
67 | - It can help to move big refactors into their own pull request
68 |
69 | Benefits:
70 |
71 | - Makes reviewer's life easier
72 | - Faster reviews mean the developer gets their feedback when the everything is still fresh in their mind
73 | - Avoids long-running feature branches
74 | - Reduces risk of developers writing conflicting code
75 | - Allows developers to build on top of each other's changes without having to build on top of someone else's feature branch (or, even worse, some combination of other people's branches)
76 | - See also [Trunk-Based Development](./Trunk-Based-Development.md)
77 |
78 | ## Resources
79 |
80 | - [Developer Tip: Keep Your Commits "Atomic"](https://www.freshconsulting.com/insights/blog/atomic-commits/)
81 | - [Commit Early, Push Often](https://www.worklytics.co/blog/commit-early-push-often)
82 |
--------------------------------------------------------------------------------
/javascript/Spread-syntax-rest-parameters-destructuring.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Spread syntax, rest parameters and destructuring
3 | description: An overview of JavaScript spread syntax, rest parameters and destructuring
4 | last_modified: 2020-05-30T15:54:15+02:00
5 | ---
6 |
7 | # Spread syntax, rest parameters and destructuring (JavaScript)
8 |
9 | ## Contents
10 |
11 | - [Spread syntax](#spread-syntax)
12 | - [Rest parameters](#rest-parameters)
13 | - [Destructuring](#destructuring)
14 | - [Array destructuring](#array-destructuring)
15 | - [Object destructuring](#object-destructuring)
16 | - [Resources](#resources)
17 |
18 | ## Spread syntax
19 |
20 | - Syntax: `...`
21 | - Allows expanding an array or string into individual elements/characters
22 | - Allows expanding an object into key-value pairs of properties
23 |
24 | Use case: expanding array into function arguments (before spread syntax, you would need to use `apply` for this)
25 |
26 | ```javascript
27 | const test = [1, 7, 3];
28 | const max = Math.max(...test); // 7
29 | ```
30 |
31 | Use case: stitching together arrays
32 |
33 | ```javascript
34 | const a = [1, 7, 3];
35 | const b = [5, ...a]; // [5, 1, 7, 3]
36 | ```
37 |
38 | ```javascript
39 | const c = [1];
40 | const d = [2, 3];
41 | const e = [...c, ...d]; // [1, 2, 3]
42 | ```
43 |
44 | Use case: shallow copy of array
45 |
46 | ```javascript
47 | const original = [1, 2, 3];
48 | const shallowCopy = [...original]
49 | ```
50 |
51 | Use case: transforming a `Set` (or other iterable) into an array (easy way of filtering array by distinct values)
52 |
53 | ```javascript
54 | const original = ["a", "b", "c", "a"];
55 | const distinct = [...new Set(original)]; // ["a", "b", "c"];
56 | ```
57 |
58 | Use case: combining objects (alternative to `Object.assign`)
59 |
60 | Note: in case of conflicts, newest overwrites oldest
61 |
62 | ```javascript
63 | const a = { prop1: "a", prop2: true };
64 | const b = { prop3: 3, ...a }; // { prop3: 3, prop1: "a", prop2: true }
65 | ```
66 |
67 | ```javascript
68 | const a = { prop1: "a", prop2: true };
69 | const b = { prop2: false, prop3: 3 };
70 | const c = { ...a, ...b }; // { prop1: "a", prop2: false, prop3: 3 }
71 | ```
72 |
73 | ```javascript
74 | const a = { prop2: true };
75 | const b = { prop2: undefined };
76 | const c = { ...a, ...b }; // {} (undefined overwrites true)
77 | ```
78 |
79 | ## Rest parameters
80 |
81 | - Syntax: `...`
82 | - Allows to represent any number of arguments as an array
83 |
84 | Example:
85 |
86 | ```javascript
87 | function test(...input) {
88 | return input;
89 | }
90 |
91 | test(1, 2, 3); // [1, 2, 3];
92 | ```
93 |
94 | ## Destructuring
95 |
96 | Allows unpacking array elements or object properties into separate variables
97 |
98 | ### Array destructuring
99 |
100 | Use case: unpacking array elements
101 |
102 | ```javascript
103 | const x = [1, 2, 3, 4, 5];
104 | const [a, b] = x; // a = 1, b = 1
105 | const [c, ...rest] = x; // c = 1, rest = [2, 3, 4, 5]
106 | const [, d] = x; // d = 2
107 | ```
108 |
109 | Use case: swapping values of variables
110 |
111 | ```javascript
112 | [a, b] = [b, a];
113 | ```
114 |
115 | Working with default values:
116 |
117 | ```javascript
118 | const [a = 1, b = 2] = [3]; // a = 3, b = 2
119 | ```
120 |
121 | ### Object destructuring
122 |
123 | Use case: unpacking object properties
124 |
125 | ```javascript
126 | const a = { prop1: "a", prop2: false, prop3: 3 };
127 | const { prop1 } = a; // prop1 = "a"
128 | const { prop2, ...b } = a; // prop2 = false, b = { prop1: "a", prop3: 3 }
129 | ```
130 |
131 | ```javascript
132 | const a = { prop1: "a" };
133 | const { prop1: newName } = a; // newName = "a"
134 | ```
135 |
136 | Working with default values
137 |
138 | ```javascript
139 | const a = { prop1: "a" };
140 | const { prop1 = "b", prop2 = false } = a; // prop1 = "a", prop2 = false
141 | ```
142 |
143 | Combining everything, plus default parameters
144 |
145 | ```javascript
146 | function test({ name: firstName = "John", lastName = "Doe" } = {}) {
147 | console.log(firstName + " " + lastName);
148 | }
149 |
150 | test(); // John Doe
151 | test({}); // John Doe
152 | test({ lastName: "Bovi" }); // John Bovi
153 | test({ name: "Cookie" }); // Cookie Doe
154 | test({ lastName: undefined }); // John Doe
155 | test({ lastName: null }); // John null
156 | ```
157 |
158 | ## Resources
159 |
160 | - [Spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)
161 | - [Rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters)
162 | - [Destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
163 |
--------------------------------------------------------------------------------
/javascript/typescript/Index-types.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Index types
3 | description: Some examples of TypeScript index types and how to use them
4 | last_modified: 2020-11-21T18:14:37.196Z
5 | ---
6 |
7 | # Index types (TypeScript)
8 |
9 | ## Contents
10 |
11 | - [Index operators](#index-operators)
12 | - [Index signatures](#index-signatures)
13 | - [Use case: mapped types](#use-case-mapped-types)
14 | - [`Readonly` and `Partial`](#readonly-and-partial)
15 | - [`Pick`](#pick)
16 | - [Use case: dictionaries with enum or type union keys](#use-case-dictionaries-with-enum-or-type-union-keys)
17 | - [Resources](#resources)
18 |
19 | ## Index operators
20 |
21 | **Index type query operator:** `keyof`
22 |
23 | ```typescript
24 | interface Test {
25 | propA: number;
26 | propB: string;
27 | }
28 |
29 | type TestKey = keyof Test;
30 | // type TestKey = "propA" | "propB"
31 | ```
32 |
33 | **Indexed access operator:** `T[K]`
34 |
35 | Can be used in generic context to indicate property types
36 |
37 | Example (adapted from [Index types](https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types)):
38 |
39 | ```typescript
40 | interface Test {
41 | propA: number;
42 | propB: string;
43 | }
44 |
45 | function getProperty(o: T, propertyName: K): T[K] {
46 | return o[propertyName]; // o[propertyName] is of type T[K]
47 | }
48 |
49 | const test: Test = { propA: 1, propB: "b" };
50 |
51 | getProperty(test, "propA"); // type number
52 | getProperty(test, "propB"); // type string
53 | ```
54 |
55 | ## Index signatures
56 |
57 | Can be used to specify structure of object with arbitrary property names
58 |
59 | ```typescript
60 | interface IndexSignature {
61 | [key: string]: boolean | number;
62 | a: boolean;
63 | b: number;
64 | }
65 |
66 | function test(input: IndexSignature) {
67 | input.a // type boolean
68 | input.b // type number
69 | input.c // type boolean | number;
70 | }
71 | ```
72 |
73 | Can also be used with generics:
74 |
75 | ```typescript
76 | interface GenericIndexSignature {
77 | [key: string]: T;
78 | }
79 |
80 | function test(input: GenericIndexSignature) {
81 | input.c // type number;
82 | input.d // type number;
83 | }
84 | ```
85 |
86 | ### Use case: mapped types
87 |
88 | Mapped types = new types based on other types
89 |
90 | #### `Readonly` and `Partial`
91 |
92 | Implementations (already provided by TypeScript language):
93 |
94 | ```typescript
95 | type Readonly = {
96 | readonly [P in keyof T]: T[P];
97 | };
98 |
99 | type Partial = {
100 | [P in keyof T]?: T[P];
101 | };
102 | ```
103 |
104 | Example:
105 |
106 | ```typescript
107 | interface Person {
108 | name: string;
109 | age: number;
110 | }
111 |
112 | type ReadonlyPerson = Readonly;
113 | // type ReadonlyPerson = { readonly name: string; readonly age: number; }
114 |
115 | type PartialPerson = Partial;
116 | // type PartialPerson = { name?: string | undefined; age? : number | undefined; }
117 | ```
118 |
119 | #### `Pick`
120 |
121 | Implementation (already provided by TypeScript language):
122 |
123 | ```typescript
124 | type Pick = {
125 | [P in K]: T[P];
126 | };
127 | ```
128 |
129 | Example:
130 |
131 | ```typescript
132 | interface Test {
133 | propA: string;
134 | propB: number;
135 | propC: boolean;
136 | }
137 |
138 | type Picked = Pick;
139 | // type Picked = { propA: string; propC: boolean; }
140 | ```
141 |
142 | ### Use case: dictionaries with enum or type union keys
143 |
144 | Example with enum keys:
145 |
146 | ```typescript
147 | enum TestEnum {
148 | First = "First",
149 | Second = "Second",
150 | Third = "Third"
151 | }
152 |
153 | type DictionaryWithAllKeys = { [key in TestEnum]: number; };
154 | type DictionaryWithSomeKeys = { [key in TestEnum]?: number; };
155 |
156 | // error: property 'Third' is missing
157 | const testAllKeys: DictionaryWithAllKeys = {
158 | First: 1,
159 | Second: 2
160 | }
161 |
162 | const testSomeKeys: DictionaryWithSomeKeys = {
163 | First: 1,
164 | Second: 2
165 | }
166 | ```
167 |
168 | Example with type union keys:
169 |
170 | ```typescript
171 | type TestUnion = "First" | "Second" | "Third";
172 |
173 | type DictionaryWithAllKeys = { [key in TestUnion]: number; };
174 | type DictionaryWithSomeKeys = { [key in TestUnion]?: number; };
175 |
176 | // error: property 'Third' is missing
177 | const testAllKeys: DictionaryWithAllKeys = {
178 | First: 1,
179 | Second: 2
180 | }
181 |
182 | const testSomeKeys: DictionaryWithSomeKeys = {
183 | First: 1,
184 | Second: 2
185 | }
186 | ```
187 |
188 | ## Resources
189 |
190 | - [Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
191 |
--------------------------------------------------------------------------------
/_website/static/img/mistermicheels.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
93 |
--------------------------------------------------------------------------------
/data/CAP-theorem.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: The CAP theorem and its implications for distributed data stores
3 | last_modified: 2020-05-30T15:54:15+02:00
4 | ---
5 |
6 | # CAP theorem
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Criticism](#criticism)
12 | - [CAP consistency vs. ACID consistency](#cap-consistency-vs-acid-consistency)
13 | - [SQL Server example](#sql-server-example)
14 | - [Resources](#resources)
15 |
16 | ## Basic idea
17 |
18 | This theorem states that it is impossible for a distributed data store to simultaneously provide more than two out of the following three guarantees:
19 |
20 | - _Consistency_: Every read returns either the relevant value as it was written by the latest successful write or an error
21 | - _Availability_: Every request receives a non-error response
22 | - _Partition tolerance_: The system keeps working, even if any number of messages is dropped or delayed by the network that connects the different instances
23 |
24 | Implications:
25 |
26 | > No distributed system is safe from network failures, thus network partitioning generally has to be tolerated. In the presence of a partition, one is then left with two options: consistency or availability. When choosing consistency over availability, the system will return an error or a time-out if particular information cannot be guaranteed to be up to date due to network partitioning. When choosing availability over consistency, the system will always process the query and try to return the most recent available version of the information, even if it cannot guarantee it is up to date due to network partitioning.
27 | >
28 | > In the absence of network failure – that is, when the distributed system is running normally – both availability and consistency can be satisfied
29 |
30 | ## Criticism
31 |
32 | - Can be misleading if presented as "pick 2 out of 3"
33 | - Every distributed system has to assume the possibility of network failures, so actually the trade-off is between consistency and availability
34 | - When the network is working correctly, you can still have both consistency and availability at the same time (you don't have to abandon 1 out of the 3 at all times)
35 | - Notion of consistency is limited and can be confusing
36 | - Consistency as defined in CAP theorem is actually linearizability (preventing a read from returning a value that's different from the last written value, basically making it seem like there is only one copy of the data rather than multiple copies which might not have caught up with each other)
37 | - There are also other consistency models in the distributed systems research, plus other uses of the term _consistency_ in the data store world
38 | - For an overview (not necessarily complete) of consistency models for distributed systems, take a look at [Consistency Models](https://jepsen.io/consistency)
39 | - Only takes into account network partitions (nodes that are alive but disconnected from each other)
40 | - Ignores dead nodes, etc.
41 |
42 | Still, the CAP theorem has been of large historical importance as it encouraged people to also explore distributed systems that limit consistency in favor of availability, which can make sense for certain large-scale web services. This has been an important inspiration for the NoSQL movement.
43 |
44 | ## CAP consistency vs. ACID consistency
45 |
46 | See also [ACID properties](./sql/ACID.md)
47 |
48 | Both mean something completely different:
49 |
50 | - CAP consistency: Every read returns either the relevant value as it was written by the latest successful write or an error
51 | - ACID consistency: The execution of the transaction must bring the database to a valid state, respecting the database’s schema
52 |
53 | In fact, when relational databases are deployed in a distributed fashion, there are typically different modes available that can have an impact on CAP consistency.
54 |
55 | ### SQL Server example
56 |
57 | See:
58 |
59 | - [SQL Server Availability Modes](https://docs.microsoft.com/en-us/sql/database-engine/availability-groups/windows/availability-modes-always-on-availability-groups?view=sql-server-2017)
60 | - [Offload read-only workload to secondary replica of an Always On availability group](https://docs.microsoft.com/en-us/sql/database-engine/availability-groups/windows/active-secondaries-readable-secondary-replicas-always-on-availability-groups?view=sql-server-2017)
61 |
62 | When setting up a high-availability cluster for Microsoft SQL Server, you have the choice between the availability modes _synchronous commit_ and _asynchronous commit_. Synchronous commit waits to return for a transaction until it has effectively been synchronized to the other instances (secondary replicas). Asynchronous commit, on the other hand, does not wait for the secondary replicas to catch up. If asynchronous commit is used and the cluster is configured to allow reads to go directly to the secondary replicas, it is possible that reads return stale data.
63 |
64 | ## Resources
65 |
66 | - [CAP theorem](https://en.wikipedia.org/wiki/CAP_theorem)
67 | - Designing Data-Intensive Applications (book by Martin Kleppmann)
68 | - [Consistency Models](https://jepsen.io/consistency)
69 |
--------------------------------------------------------------------------------
/architecture-design/Duplication.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Why duplication is not always bad
3 | last_modified: 2021-12-27T16:49:37.759Z
4 | ---
5 |
6 | # Duplication
7 |
8 | ## Contents
9 |
10 | - [Real versus false duplication](#real-versus-false-duplication)
11 | - [Drawbacks of duplication](#drawbacks-of-duplication)
12 | - [Benefits of duplication](#benefits-of-duplication)
13 | - [The dangers of removing false duplication](#the-dangers-of-removing-false-duplication)
14 | - [Advice](#advice)
15 | - [Resources](#resources)
16 |
17 | ## Real versus false duplication
18 |
19 | - **Real duplication:** duplicates will always need to do the exact same thing
20 | - This is the kind of duplication you really want to avoid
21 | - Good use case for the **Don't Repeat Yourself** ([DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)) principle
22 | - **False duplication:** code/structures/... that are identical now but likely to change independently of each other in the future
23 | - The fact that two things are the same at this moment does not necessarily mean that they are real duplicates and that that apparent duplication is a bad thing
24 | - Attempts to get rid of false duplication tend to lead to unnecessary coupling through shared code, which will then come back to bite you when the “duplicates” suddenly need to change independently of each other
25 |
26 | ## Drawbacks of duplication
27 |
28 | - Duplicated work when making changes, because changes need to get applied to every duplicate
29 | - Developers can forget to adjust (some of) the duplicates when fixing bugs, adding behavior, ...
30 | - Inconsistencies between duplicates could lead to unexpected behavior, corrupted data, incorrectly believing that the team has removed a certain important bug, ...
31 | - Developers might refactor some of the duplicates while forgetting others, making it much harder to recognize the duplication in the future
32 |
33 | ## Benefits of duplication
34 |
35 | Mostly, it's about flexibility!
36 |
37 | - Allows for duplicates to evolve in different directions if needed
38 | - Later on, you can still decide to merge (part of) the duplicated code into an abstraction to reduce duplication
39 |
40 | ## The dangers of removing false duplication
41 |
42 | What typically happens when trying to get rid of false duplication:
43 |
44 | 1. Someone sees the duplication and creates an abstraction (function, class, ...) holding the duplicated code. The abstraction is now shared between all places that had the duplicated code before.
45 | 2. Requirements change and one of the places that had the duplicated code now needs to do something slightly different.
46 | 3. The developer implementing the change sees the abstraction and feels obligated to keep it. They extend it with "just one more parameter" or "just one more condition" to trigger the slightly different behavior. This makes the logic just a bit more complex and makes it just a bit more difficult to follow what the code is doing in one of the originally duplicated cases.
47 | 4. Repeat 2 and 3 until the abstraction's code becomes a mess containing way too much behavior as well as being very risky and hard to modify when needed. At this point, it's often even unclear which parts of the behavior belong to which of the original 'duplicates'.
48 |
49 | In the end, you have a tangled, hard-to-maintain mess that is also hard to split up into different, more maintainable parts.
50 |
51 | ## Advice
52 |
53 | - Don't blindly follow the Don't Repeat Yourself ([DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)) principle whenever you see any kind of duplication
54 | - Check whether you're dealing with real or false duplication
55 | - Don't take DRY to its extreme, it's ok that some things are defined in multiple places
56 | - Example: Fields in DB vs fields in UI. In theory, you could generate a UI based on DB structure, or generate both DB structure and UI based from a single place in the codebase. However, this would likely result in a UI with terrible user experience. DB design and UI design have very different purposes, which means they likely need to represent data in a different way, even if it's technically the same data.
57 | - Better principle to follow: **Avoid Hasty Abstractions** ([AHA Programming](https://kentcdodds.com/blog/aha-programming))
58 | - _"Prefer duplication over the wrong abstraction"_
59 | - If you're not sure whether duplicates will need to change independently in the future, it's probably best to keep the duplication for the sake of future flexibility
60 | - Only apply DRY once you are confident that you're dealing with real duplication
61 | - The more you know about the requirements and the directions in which they can change, the more DRY you can make your code
62 |
63 | ## Resources
64 |
65 | - [AHA Programming](https://kentcdodds.com/blog/aha-programming)
66 | - [The Wrong Abstraction](https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction)
67 | - [Beginner’s Guide To Abstraction](https://jesseduffield.com/Beginners-Guide-To-Abstraction/)
68 | - [Moist code - Why code should not be completely DRY](https://startup-cto.net/moist-code-why-code-should-not-be-completely-dry)
69 |
--------------------------------------------------------------------------------
/web/css/Selectors.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Selectors
3 | description: An overview of CSS selectors and how to combine them
4 | last_modified: 2020-05-30T15:54:15+02:00
5 | ---
6 |
7 | # Selectors (CSS)
8 |
9 | ## Contents
10 |
11 | - [Selector types](#selector-types)
12 | - [Type selector](#type-selector)
13 | - [Universal selector](#universal-selector)
14 | - [Class selector](#class-selector)
15 | - [ID selector](#id-selector)
16 | - [Attribute selector](#attribute-selector)
17 | - [Pseudo-class selector](#pseudo-class-selector)
18 | - [Pseudo-element selector](#pseudo-element-selector)
19 | - [Combining selectors](#combining-selectors)
20 | - [Selector lists using `,`](#selector-lists-using-)
21 | - [Same-element combinations](#same-element-combinations)
22 | - [Descendant combinator](#descendant-combinator)
23 | - [Child combinator](#child-combinator)
24 | - [Adjacent sibling combinator](#adjacent-sibling-combinator)
25 | - [General sibling combinator](#general-sibling-combinator)
26 | - [Resources](#resources)
27 |
28 | ## Selector types
29 |
30 | ### Type selector
31 |
32 | Selects based on HTML element type
33 |
34 | ```css
35 | h1 {
36 | color: red;
37 | }
38 | ```
39 |
40 | ### Universal selector
41 |
42 | Selects all elements
43 |
44 | ```css
45 | * {
46 | color: red;
47 | }
48 | ```
49 |
50 | ### Class selector
51 |
52 | Selects elements based on class
53 |
54 | ```css
55 | .error-text {
56 | color: red;
57 | }
58 | ```
59 |
60 | ### ID selector
61 |
62 | Selects elements based on ID
63 |
64 | ```css
65 | #main-text {
66 | color: black;
67 | }
68 | ```
69 |
70 | ### Attribute selector
71 |
72 | Select elements based on attributes
73 |
74 | ```css
75 | [disabled] {
76 | color: red;
77 | }
78 | ```
79 |
80 | ### Pseudo-class selector
81 |
82 | Selects elements that are in a specific state
83 |
84 | Typically combined with other selectors (see also below)
85 |
86 | ```css
87 | a:hover {
88 | color: red;
89 | }
90 | ```
91 |
92 | [Pseudo-classes reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#Index_of_standard_pseudo-classes)
93 |
94 | Special case: the **negation pseudo-class**
95 |
96 | ```css
97 | /* matches any element that is not a paragraph */
98 | :not(p) {
99 | color: blue;
100 | }
101 | ```
102 |
103 | ### Pseudo-element selector
104 |
105 | Selects specific part of an element
106 |
107 | Typically combined with other selectors
108 |
109 | ```css
110 | p::first-line {
111 | text-transform: uppercase;
112 | }
113 | ```
114 |
115 | [Pseudo-elements reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements#Index_of_standard_pseudo-elements)
116 |
117 | ## Combining selectors
118 |
119 | ### Selector lists using `,`
120 |
121 | No effect other than reducing code duplication
122 |
123 | Example: before
124 |
125 | ```css
126 | h1 {
127 | color: blue;
128 | }
129 |
130 | .special {
131 | color: blue;
132 | }
133 | ```
134 |
135 | Example: after
136 |
137 | ```css
138 | h1, .special {
139 | color: blue;
140 | }
141 | ```
142 |
143 | ### Same-element combinations
144 |
145 | Combine multiple selectors that all need to apply to the same element
146 |
147 | Example: select all hyperlinks with class `test` that the user hovers over
148 |
149 | ```css
150 | a.test:hover {
151 | color: red;
152 | }
153 | ```
154 |
155 | ### Descendant combinator
156 |
157 | Typically represented by a single space (` `) character
158 |
159 | Elements matched by the second selector are selected if they have an ancestor matching the first selector
160 |
161 | Example: select all spans that are directly or indirectly inside a div with class test
162 |
163 | ```css
164 | div.test span {
165 | color: red;
166 | }
167 | ```
168 |
169 | ### Child combinator
170 |
171 | Represented by the `>` sign
172 |
173 | Same as descendant combinator, but only considers the direct parent of an element
174 |
175 | Example: select all spans that are a direct child of a div with class test
176 |
177 | ```css
178 | div.test > span {
179 | color: red;
180 | }
181 | ```
182 |
183 | ### Adjacent sibling combinator
184 |
185 | Represented by the `+` sign
186 |
187 | Matches an element matching the second selector if that element immediately follows an element matching the first selector and they both have the same parent
188 |
189 | Example: select all paragraphs that immediately follow an image
190 |
191 | ```css
192 | img + p {
193 | color: red;
194 | }
195 | ```
196 |
197 | ### General sibling combinator
198 |
199 | Represented by the `~` sign
200 |
201 | Matches an element matching the second selector if that element follows an element matching the first selector (but not necessarily immediately) and they both have the same parent
202 |
203 | Example: select paragraphs that come after any image with the same parent
204 |
205 | ```css
206 | img ~ p {
207 | color: red;
208 | }
209 | ```
210 |
211 | ## Resources
212 |
213 | - [CSS - The Complete Guide 2020 (incl. Flexbox, Grid & Sass)](https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/)
214 | - [CSS selectors](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors)
215 |
--------------------------------------------------------------------------------
/javascript/typescript/Nullable-types-optional-parameters-properties.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Nullable types and optional parameters/properties
3 | description: An overview of how TypeScript deals with null, undefined and optional parameters/properties
4 | last_modified: 2022-01-31T10:44:35.294Z
5 | ---
6 |
7 | # Nullable types and optional parameters/properties (TypeScript)
8 |
9 | ## Contents
10 |
11 | - [Nullable types](#nullable-types)
12 | - [Optional chaining](#optional-chaining)
13 | - [Non-null assertion operator](#non-null-assertion-operator)
14 | - [Optional parameters](#optional-parameters)
15 | - [Optional properties](#optional-properties)
16 | - [Resources](#resources)
17 |
18 | ## Nullable types
19 |
20 | Two special types: `null` and `undefined`
21 |
22 | - Treated as different from each other, because that's what JavaScript does as well
23 | - By default, assignable to anything, but this can be changed by enabling the `--strictNullChecks` flag
24 | - Recommended to enable this, allow type checking to prevent a lot of potential runtime errors
25 |
26 | Example without `--strictNullChecks`:
27 |
28 | ```typescript
29 | // everything ok according to compiler
30 | const test1: string = undefined;
31 | const test2: string = null;
32 | const test3: string | undefined = undefined;
33 | const test4: string | undefined = null;
34 | const test5: string | null = undefined;
35 | const test6: string | null = null;
36 | const test7: string | null | undefined = undefined;
37 | const test8: string | null | undefined = null;
38 | ```
39 |
40 | Example with `--strictNullChecks`:
41 |
42 | ```typescript
43 | const test1: string = undefined; // error
44 | const test2: string = null; // error
45 | const test3: string | undefined = undefined;
46 | const test4: string | undefined = null; // error
47 | const test5: string | null = undefined; // error
48 | const test6: string | null = null;
49 | const test7: string | null | undefined = undefined;
50 | const test8: string | null | undefined = null;
51 | ```
52 |
53 | ## Optional chaining
54 |
55 | (introduced in TypeScript 3.7)
56 |
57 | Operator `?` that allows to stop evaluation when something is `null` or `undefined`
58 |
59 | Motivation: accessing `instance.prop.otherProp.nextProp` where at each level the property may be `null` or `undefined` (leading to runtime errors if we fail to check for it)
60 |
61 | Example:
62 |
63 | ```typescript
64 | let x = instance.prop?.otherProp;
65 | // is equivalent to
66 | let x = instance.prop === null || instance.prop === undefined ? undefined : instance.prop.otherProp;
67 | ```
68 |
69 | Note that, if evaluation stops because something is `null`, the result is still `undefined`
70 |
71 | ## Non-null assertion operator
72 |
73 | Operator `!` that allows to let TypeScript know you are sure that a certain value is not `null` or `undefined` (useful in situations where the code is too complex for TypeScript to figure this out by itself)
74 |
75 | Example (with `--strictNullChecks`):
76 |
77 | ```typescript
78 | function test(str: string | null | undefined) {
79 | const ensureStringDefined = function () {
80 | if (str === null || str === undefined) {
81 | str = "test";
82 | }
83 | }
84 |
85 | ensureStringDefined();
86 | console.log(str.toUpperCase()); // error
87 | console.log(str!.toUpperCase()); // ok
88 | }
89 | ```
90 |
91 | ## Optional parameters
92 |
93 | If `--strictNullChecks` is enabled, making a parameter optional automatically adds ` | undefined` to its type
94 |
95 | Example without `--strictNullChecks`:
96 |
97 | ```typescript
98 | function test(a: string, b?: string) {
99 | return a;
100 | }
101 |
102 | // everything ok according to compiler
103 | test("a");
104 | test("a", undefined);
105 | test("a", null);
106 | ```
107 |
108 | Example with `--strictNullChecks`:
109 |
110 | ```typescript
111 | function test(a: string, b?: string) {
112 | return a;
113 | }
114 |
115 | test("a");
116 | test("a", undefined);
117 | test("a", null); // error
118 | ```
119 |
120 | Note: an optional parameter is not completely the same as a parameter that needs to be provided but can be undefined!
121 |
122 | ```typescript
123 | function test2(a: string, b: string | undefined) {
124 | return a;
125 | }
126 |
127 | test2("b"); // error because of missing argument, even without --strictNullChecks
128 | test2("b", undefined); // ok
129 | ```
130 |
131 | You can use this to force the code using your function to be very explicit about passing in `undefined`
132 |
133 | ## Optional properties
134 |
135 | Example without `--strictNullChecks`:
136 |
137 | ```typescript
138 | class Test {
139 | a: number = 1;
140 | b?: number;
141 | }
142 |
143 | // everything ok according to compiler
144 | let test = new Test();
145 | test.a = 12;
146 | test.a = undefined;
147 | test.a = null;
148 | test.b = 12;
149 | test.b = undefined;
150 | test.b = null;
151 | ```
152 |
153 | Example with `--strictNullChecks`:
154 |
155 | ```typescript
156 | class Test {
157 | a: number = 1;
158 | b?: number;
159 | }
160 |
161 | let test = new Test();
162 | test.a = 12;
163 | test.a = undefined; // error
164 | test.a = null; // error
165 | test.b = 12;
166 | test.b = undefined;
167 | test.b = null; // error
168 | ```
169 |
170 | ## Resources
171 |
172 | - [Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
173 |
--------------------------------------------------------------------------------
/processes-techniques/Dealing-with-uncertainty.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Ideas/techniques to help you be productive in the face of uncertainty
3 | last_modified: 2020-11-28T21:26:07.929Z
4 | ---
5 |
6 | # Dealing with uncertainty
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Analyzing uncertainty](#analyzing-uncertainty)
12 | - [Dealing with uncertain tasks](#dealing-with-uncertain-tasks)
13 | - [Removing technical uncertainty](#removing-technical-uncertainty)
14 | - [Removing functional uncertainty](#removing-functional-uncertainty)
15 | - [Resources](#resources)
16 |
17 | ## Basic idea
18 |
19 | - Uncertainty about what to build and how to build it can hugely reduce your productivity and happiness as a developer
20 | - Unclear goals
21 | - Unclear acceptance criteria
22 | - Unclear how to achieve things from the technological side
23 | - It can be useful to make this uncertainty explicit
24 | - There are some useful techniques for removing uncertainty
25 | - In some cases, you might be able to start "working around the uncertainty"
26 | - There are likely not only _known unknowns_ but also _unknown unknowns_ that only surface when you dive deep into the functionality or solution approach
27 | - Unknowns are fact of life in software development
28 | - It can be useful to make a conscious effort to tease them out early through mockups, prototypes, ... (see also [Fail fast](../mindset/Fail-fast.md))
29 |
30 | ## Analyzing uncertainty
31 |
32 | Framework used at ThoughtWorks:
33 |
34 | 
35 |
36 | ([image source](https://dev.to/kmruiz/understanding-uncertainty-in-software-development-an-agile-way-22m6))
37 |
38 | Axes:
39 |
40 | - Technical certainty: how well does the development team understand how to build the feature?
41 | - Business agreement: how well does business agree on what goes into the feature and how the system should behave?
42 |
43 | Different areas of the diagram:
44 |
45 | - **Red with cross**: the task can't be done at the moment and you might also want to split/redefine it later on
46 | - **Red**: the task needs clarification before it can be started
47 | - **Yellow**: the task is not entirely clear, but it should be possible to start tackling it
48 | - **Green**: it's clear what to do, the implementation should be relatively straightforward and predictable
49 |
50 | Benefits of the framework:
51 |
52 | - Makes uncertainty explicit
53 | - Can help to start conversations needed to get rid of the uncertainty
54 | - During conversations, focus on writing down what the questions and unknowns are that need to be resolved
55 |
56 | ## Dealing with uncertain tasks
57 |
58 | - Prioritize getting rid of the uncertainty
59 | - In SCRUM, it can make sense to define a Spike for this ([Spikes in Scrum](https://medium.com/@leanscrummaster/spikes-in-scrum-3c80a65dce58))
60 | - For highly uncertain tasks, it can make sense to postpone the implementation to the next sprint
61 | - Assign someone to take the lead in removing the uncertainty
62 | - Make sure to keep a clear list of what questions need to be answered
63 | - If some parts are already clear, see if you can get started on implementing those
64 | - You might be able to "work around the uncertainty"
65 | - It might be possible to split off some unclear parts into their own tasks
66 | - It might make sense to prioritize clarification of unclear tasks over implementation of clear tasks
67 | - Tease out unknown unknowns as soon as possible
68 | - Ensure that the team is not suddenly blocked by a backlog with only unclear tasks
69 | - See also [Fail fast](../mindset/Fail-fast.md)
70 |
71 | ### Removing technical uncertainty
72 |
73 | Useful technique: time-boxing
74 |
75 | - Pick a predefined amount of time (2 hours, 1 day, ...) to spend on researching and experimenting
76 | - Can be done by one person or a small sub-team
77 | - Research by itself is often not enough. You might need to build some kind of prototype to really get a feel for what works and what doesn't. See also [Fail fast](../mindset/Fail-fast.md).
78 | - When the time is up, get back to the team with the results
79 | - Decide together with the team if further time-boxed sessions are needed/appropriate
80 |
81 | Why it helps to time-box:
82 |
83 | - Helps to prevent going down rabbit holes or getting stuck in analysis paralysis
84 | - Forces regularly checking in with the team
85 | - Can lead to useful ideas from the team for further time-boxed sessions
86 | - Allows correcting course if needed based on feedback from the team
87 | - The team can function as compass to help you focus on the essence
88 | - See also [Fail fast](../mindset/Fail-fast.md)
89 | - Allows re-evaluating whether the effort is actually worth it
90 |
91 | ### Removing functional uncertainty
92 |
93 | It often helps to do some kind of prototyping: mockups, wireframes, page flows, ... (see also [Fail fast](../mindset/Fail-fast.md))
94 |
95 | ## Resources
96 |
97 | - [Understanding uncertainty in software development: an Agile way](https://dev.to/kmruiz/understanding-uncertainty-in-software-development-an-agile-way-22m6)
98 | - [Lean Inception - Technical and Business Review](https://martinfowler.com/articles/lean-inception/tech-and-business-review.html)
99 | - [Dealing With Unknowns In Software Development](https://blog.professorbeekums.com/managing-unknowns/)
100 | - [Spikes in Scrum](https://medium.com/@leanscrummaster/spikes-in-scrum-3c80a65dce58)
101 |
--------------------------------------------------------------------------------
/mindset/It-depends.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: Everything is a trade-off
3 | last_modified: 2020-11-21T18:14:37.203Z
4 | ---
5 |
6 | # It depends
7 |
8 | ## Contents
9 |
10 | - [Basic idea](#basic-idea)
11 | - [Trade-offs](#trade-offs)
12 | - [Make trade-offs explicit](#make-trade-offs-explicit)
13 | - [No perfect solutions!](#no-perfect-solutions)
14 | - [Good solutions and flexibility](#good-solutions-and-flexibility)
15 | - [Best practices](#best-practices)
16 | - [Tools, not rules](#tools-not-rules)
17 | - [Test-driving approaches](#test-driving-approaches)
18 | - [Documenting the decision process](#documenting-the-decision-process)
19 | - [Implementing the chosen approach](#implementing-the-chosen-approach)
20 | - [Moving to a different approach](#moving-to-a-different-approach)
21 | - [Resources](#resources)
22 |
23 | ## Basic idea
24 |
25 | - What technology should I use for my web application’s back end? _It depends_
26 | - Should I use a relational or NoSQL database? And which one? _It depends_
27 | - Should I really have more unit than integration tests? _It depends_
28 | - Is it bad to have an anemic domain model? _It depends_
29 | - Should we run our project using SCRUM? _It depends_
30 |
31 | ## Trade-offs
32 |
33 | Almost every decision you make when developing or designing software is a trade-off!
34 |
35 | Areas to take into account:
36 |
37 | - initial development effort
38 | - maintenance effort
39 | - correctness
40 | - performance
41 | - usability
42 |
43 | Tradeoffs not only between these factors but also within these areas! E.g. performance for use case A vs performance for use case B
44 |
45 | ### Make trade-offs explicit
46 |
47 | - Explicitly list the tradeoffs you are making
48 | - Designing two different solutions and looking at how they compare to each other can help you identify relevant tradeoffs
49 |
50 | ## No perfect solutions!
51 |
52 | _The Best Solution®_ or _The Right Way™_ typically do not exist!
53 |
54 | Every approach will likely have its own drawbacks or limitations that another approach doesn't have.
55 |
56 | ## Good solutions and flexibility
57 |
58 | Instead of looking for perfect solutions, look for two things:
59 |
60 | - Good solutions that make sense and for which we don’t see an alternative that is clearly much better
61 | - Flexibility through good architecture and coding practices
62 |
63 | Choosing between solutions:
64 |
65 | - One that stands out: go for it!
66 | - Hard time choosing: typically means they are all good! implement simplest one!
67 | - Quickest way to working solution
68 | - Implementing gives better understanding of problem and benefits/drawbacks of current solution
69 |
70 | Flexibility:
71 |
72 | - Good architecture and coding practices provide some degree of flexibility to change your choice later on
73 | - How much flexibility do we need? _It depends_
74 | - Additional flexibility typically comes a the expense of additional layers of abstraction and complexity
75 |
76 | ## Best practices
77 |
78 | Best practices:
79 |
80 | - Widely accepted as good solutions
81 | - If there is one clear best practice approach regarding your problem and you don’t see a significant reason not to use it, just go with that approach!
82 | - Does not mean they are perfect!
83 | - Some situations where you would be better off using another approach
84 | - Sometimes even several completely different best practice solutions to the same problem!
85 | - The more discussion over which is best, the more likely both are valid options
86 |
87 | ## Tools, not rules
88 |
89 | Methodologies (DDD, SCRUM, ...) are tools, not rules!
90 |
91 | - Not necessarily applicable to every situation
92 | - Not always possible/desired to be completely strict about "rules"
93 | - Often makes sense to adjust the details of approach to fit the specific requirements of your project and team
94 | - Often, different people already have different interpretations of the rules regarding those details!
95 |
96 | ## Test-driving approaches
97 |
98 | It can help to compare candidate approaches through techniques like prototyping (see also [Fail fast](./Fail-fast.md))
99 |
100 | ## Documenting the decision process
101 |
102 | Document options, trade-offs, ...
103 |
104 | Helps to reevaluate approach at a later time if new option pops up or situation changes!
105 |
106 | ## Implementing the chosen approach
107 |
108 | The approach you choose will likely still some drawbacks/limitations, don't let this block you!
109 |
110 | - Actually commit to implementing the chosen approach and giving it a fair chance
111 | - Don't keep second-guessing your decision after you've made it
112 | - If you're afraid you'll run into some unforeseen drawbacks/limitations, plan your implementation in such a way that they will turn up sooner rather than later (see also [Fail fast](./Fail-fast.md))
113 |
114 | ## Moving to a different approach
115 |
116 | What if, for some reason, you are convinced that the approach you are currently using is clearly inferior to some other approach?
117 |
118 | Even if architecture and code are flexible, there are some costs and risks associated with making the change. The benefits of switching to the other approach may or may not outweigh those costs and risks.
119 |
120 | So, should you make the change? _It depends._
121 |
122 | ## Resources
123 |
124 | - [Software Architecture is Overrated, Clear and Simple Design is Underrated](https://blog.pragmaticengineer.com/software-architecture-is-overrated/)
125 | - [Five Worlds](https://www.joelonsoftware.com/2002/05/06/five-worlds/)
126 |
--------------------------------------------------------------------------------
/web/css/Positioning.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Positioning
3 | description: Positioning elements using CSS
4 | last_modified: 2020-05-30T15:54:15+02:00
5 | ---
6 |
7 | # Positioning (CSS)
8 |
9 | ## Contents
10 |
11 | - [Basic idea](#basic-idea)
12 | - [Positioning types](#positioning-types)
13 | - [Static positioning](#static-positioning)
14 | - [Relative positioning](#relative-positioning)
15 | - [Absolute positioning](#absolute-positioning)
16 | - [Fixed positioning](#fixed-positioning)
17 | - [Sticky positioning](#sticky-positioning)
18 | - [An element's containing block](#an-elements-containing-block)
19 | - [Extra: z-index](#extra-z-index)
20 | - [Resources](#resources)
21 |
22 | ## Basic idea
23 |
24 | - Allows taking elements out of normal document flow
25 | - Example: one element on top of another
26 | - Example: element remaining in same place when user scrolls the page
27 | - Controlled through `position` property
28 | - Note: For creating entire layouts, Flexbox and the CSS Grid are likely better options
29 |
30 | ## Positioning types
31 |
32 | ### Static positioning
33 |
34 | - Default positioning type
35 | - "let the element take its normal position in the document"
36 |
37 | ### Relative positioning
38 |
39 | - Default placement same as static positioning
40 | - Same effect on surrounding elements as static positioning (still takes the same amount of space in the same location)
41 | - Can adjust position **relative to default placement** using the `top`, `bottom`, `left` and `right` properties
42 | - Indicate the element being pushed away from its normal position
43 | - Example: `top: 30px;` will make the element sit 30px lower than its default position
44 | - These properties do not change the effect the element has on its surrounding elements!
45 | - Can be used to make the element overlap with surrounding elements
46 |
47 | ### Absolute positioning
48 |
49 | - No longer part of normal document flow!
50 | - Does not push surrounding elements away
51 | - Exists in its own layer, separate from other elements
52 | - Can adjust position **relative to sides of [containing block](#an-elements-containing-block)** using the `top`, `bottom`, `left` and `right` properties
53 | - Containing block: see below
54 | - Indicate the element being pushes away from the sides of the containing block
55 | - Example: `top: 30px;` will make the element sit 30px lower than the top of its container element
56 | - Useful for UI features that sit on top of other elements without interfering with them: popups, rollover panels, elements that can be dragged and dropped, ...
57 |
58 | ### Fixed positioning
59 |
60 | - Same as absolute positioning, but element is positioned relative to the browser's viewport
61 | - Element stays in same position relative to viewport, even if user scrolls
62 | - Can adjust position **relative to viewport** using the `top`, `bottom`, `left` and `right` properties
63 | - Can be very useful for things like navigation menus
64 |
65 | ### Sticky positioning
66 |
67 | - Newer than the others
68 | - Hybrid between relative and fixed positioning
69 | - Makes element acts like relatively positioned one until it is scrolled to a certain point, after which is becomes fixed (to prevent it from being scrolled out of the viewport)
70 | - Interesting use case: scrollable page with different headings, each heading sticks to the top of the page as it is reached
71 |
72 | ## An element's containing block
73 |
74 | Affects size and position of element:
75 |
76 | - Basis for computation of percentage values applied to width and height
77 | - Basis for offset computations of absolutely positioned element
78 |
79 | Identifying the containing block (see also [Box model](./Box-model.md)):
80 |
81 | - If the element's position is **static**, **relative** or **sticky**, the containing block is the edge of the _content_ box of the nearest ancestor element that is either a block box or establishes a formatting context (which means it can be a table container, flex container, grid container, or the block container itself)
82 | - If the element's position is **absolute**, the containing block is the edge of the _padding_ box of the nearest ancestor element that does _not_ have static positioning
83 | - If the element's position is **fixed**, the containing block is the viewport (or the page area in case of paged media)
84 | - For elements with position **absolute** or **fixed**, there are also some special cases described here: [Layout and the containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block)
85 |
86 | Note: the containing block for the root element (the `` tag) is called the **initial containing block** and has the dimensions of the viewport (or the page area in case of paged media)
87 |
88 | ## Extra: z-index
89 |
90 | - Determines, if elements overlap, which element is on top of the other
91 | - This is also important for making elements clickable! If multiple elements overlap beneath the mouse pointer, the one receiving the click event will be the one that sits on top of the others
92 | - Property `z-index` accepts unitless values (default is 0)
93 | - Higher values are considered to be on top of lower values
94 |
95 | ## Resources
96 |
97 | - [CSS - The Complete Guide 2020 (incl. Flexbox, Grid & Sass)](https://www.udemy.com/course/css-the-complete-guide-incl-flexbox-grid-sass/)
98 | - [Positioning](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Positioning)
99 | - [Layout and the containing block](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block)
100 |
--------------------------------------------------------------------------------
/java/concurrency-details/Locking.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Locking
3 | description: Some details regarding locking as a low-level concurrency tool in Java
4 | last_modified: 2020-05-31T14:45:09+02:00
5 | ---
6 |
7 | # Locking (Java)
8 |
9 | ## Contents
10 |
11 | - [A word of caution](#a-word-of-caution)
12 | - [Locks](#locks)
13 | - [The `synchronized` keyword](#the-synchronized-keyword)
14 | - [Using locks to coordinate between threads](#using-locks-to-coordinate-between-threads)
15 | - [Resources](#resources)
16 |
17 | ## A word of caution
18 |
19 | Note: locking is a low-level concurrency tool typically used by system programmers writing things like web servers or middleware. When writing normal applications, it's probably easier and safer to use higher-level concurrency tools (see [Concurrency](../Concurrency.md) and the thread-safe date structures in [Thread safety](./Thread-safety.md)).
20 |
21 | ## Locks
22 |
23 | Locks can be used to implement _critical sections_, parts of the code that can only be executed entirely, without being interrupted, by only one single thread at a time
24 |
25 | Example of critical section using lock:
26 |
27 | ```java
28 | Lock countLock = new ReentrantLock(); // explicit lock, shared among threads
29 | int count = 0; // shared among threads
30 |
31 | // some thread
32 | {
33 | countLock.lock(); // blocks if some other thread holds the lock
34 |
35 | try {
36 | // do something complex
37 | count++;
38 | } finally {
39 | countLock.unlock(); // allows another thread to acquire the lock
40 | }
41 | }
42 | ```
43 |
44 | It is important to release the lock in the `finally` clause, so it is always released at the end of the operation even if an exception occurred
45 |
46 | The above example is simple, but implementing locking yourself can get tricky. You might have inadequate locking, you might have deadlocks, ... Therefore, it is recommended to use the other tools listed in [Concurrency](../Concurrency.md) when possible.
47 |
48 | ## The `synchronized` keyword
49 |
50 | The code above used an explicit lock object. This isn't strictly necessary, because every object also has an _intrinsic lock_. This lock can be used using the `synchronized` keyword.
51 |
52 | ```java
53 | // this ...
54 | synchronized(obj) {
55 | // critical section
56 | }
57 |
58 | // ... is equivalent to this
59 | obj.intrinsicLock.lock(); // note: there is not really a field named intrinsicLock
60 |
61 | try {
62 | // critical section
63 | } finally {
64 | obj.intrinsicLock.unlock();
65 | }
66 | ```
67 |
68 | You can also declare a method as `synchronized`
69 |
70 | ```java
71 | // this ...
72 | public synchronized void theMethod() {
73 | // body
74 | }
75 |
76 | // ... is equivalent to this
77 | public void theMethod() {
78 | this.intrinsicLock.lock();
79 |
80 | try {
81 | // body
82 | } finally {
83 | this.intrinsicLock.unlock();
84 | }
85 | }
86 | ```
87 |
88 | A pattern using intrinsic locks that you might see is that an object with `synchronized` methods is used inside a `synchronized` block locking on that object:
89 |
90 | ```java
91 | synchronized (theObject) {
92 | theObject.synchronizedMethod();
93 | theObject.otherSynchronizedMethod();
94 | }
95 | ```
96 |
97 | Note: locks also guarantee visibility. More specifically, changes that happen before releasing a lock are visible to anyone acquiring the same lock afterwards. For more about visibility, see [Thread safety](./Thread-safety.md).
98 |
99 | ## Using locks to coordinate between threads
100 |
101 | Suppose we have a simple `Queue` class with synchronized methods:
102 |
103 | ```java
104 | public class Queue {
105 | public synchronized void add(Object element) {
106 | // add element at the end
107 | }
108 |
109 | public synchronized Object remove() {
110 | // return and remove element at head, or return null if the queue is empty
111 | }
112 |
113 | pubic synchronized boolean isEmpty() {
114 | // returns true if and only if the queue is empty
115 | }
116 | }
117 | ```
118 |
119 | Now, we want to replace the `remove()` method by a method `take()` that blocks until an element is available. This means that, if the queue is empty, the `take()` method needs to stop executing, allow other threads to obtain the lock (otherwise, no elements can be added) and then continue when an element is available. This can be implemented using `wait()` and `notifyAll()`.
120 |
121 | ```java
122 | public synchronized Object take() {
123 | while(this.isEmpty()) {
124 | wait(); // thread gives up the lock and will not run again until it is notified
125 | }
126 |
127 | // return and remove element at head
128 | }
129 |
130 | public synchronized void add(Object element) {
131 | // add element at the end
132 | notifyAll(); // notifies all waiting threads on the intrinsic lock
133 | }
134 | ```
135 |
136 | Some important remarks:
137 |
138 | - The call to `wait()` should happen inside a while loop checking for the condition. This is a best practice and it prevents issues if more than one thread was waiting inside the `take()` method or a method other than `add()` calls `notifyAll()`
139 | - There is also a method `notify()` that only unblocks one waiting thread. This might be more efficient, but it can lead to issues it the waiting thread that is unblocked finds that it still wants to wait. In that case, that thread is just blocked again, while there might also be other blocked threads that can actually continue at this point. Typically, it's a better idea to just call `notifyAll()`.
140 |
141 | ## Resources
142 |
143 | - Core Java SE 9 for the Impatient (book by Cay S. Horstmann)
144 |
--------------------------------------------------------------------------------
/javascript/typescript/Type-guards.md:
--------------------------------------------------------------------------------
1 | ---
2 | tree_title: Type guards
3 | description: An overview of how to use TypeScript type guards, including creating your own custom ones
4 | last_modified: 2020-10-17T18:41:29.849Z
5 | ---
6 |
7 | # Type guards (TypeScript)
8 |
9 | ## Contents
10 |
11 | - [Basic idea](#basic-idea)
12 | - [Built-in type guards](#built-in-type-guards)
13 | - [`typeof` type guards](#typeof-type-guards)
14 | - [`instanceof` type guards](#instanceof-type-guards)
15 | - [Type guards based on common property](#type-guards-based-on-common-property)
16 | - [Type guards based on available properties](#type-guards-based-on-available-properties)
17 | - [User-defined type guards](#user-defined-type-guards)
18 | - [Resources](#resources)
19 |
20 | ## Basic idea
21 |
22 | - Test, at runtime, whether a certain value is of a certain type
23 | - TypeScript compiler can use this information to make better assumptions
24 |
25 | ## Built-in type guards
26 |
27 | ### `typeof` type guards
28 |
29 | ```typescript
30 | function test(input: string | string[]) {
31 | input.split(""); // compiler error
32 | input.filter(() => true); // compiler error
33 |
34 | if (typeof input === "string") {
35 | // input has type string here
36 | return input.split("");
37 | } else {
38 | // input has type string[] here
39 | return input.filter(() => true);
40 | }
41 | }
42 | ```
43 |
44 | ### `instanceof` type guards
45 |
46 | ```typescript
47 | class ClassA {
48 | methodA() {
49 | return true;
50 | }
51 | }
52 |
53 | class ClassB {
54 | methodB() {
55 | return true;
56 | }
57 | }
58 |
59 | function test(instance: ClassA | ClassB) {
60 | instance.methodA(); // compiler error
61 | instance.methodB(); // compiler error
62 |
63 | if (instance instanceof ClassA) {
64 | // instance has type ClassA here
65 | instance.methodA();
66 | } else {
67 | // instance has type ClassB here
68 | instance.methodB();
69 | }
70 | }
71 | ```
72 |
73 | ### Type guards based on common property
74 |
75 | Can be used to implement _Discriminating Unions_ (see [Discriminating Unions](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions)):
76 |
77 | - Types with common property indicating type
78 | - A type alias that is the union of these types
79 | - Type guards on the common property
80 |
81 | Example:
82 |
83 | ```typescript
84 | interface Square {
85 | kind: "square";
86 | size: number;
87 | }
88 |
89 | interface Rectangle {
90 | kind: "rectangle";
91 | width: number;
92 | height: number;
93 | }
94 |
95 | interface Circle {
96 | kind: "circle";
97 | radius: number;
98 | }
99 |
100 | type Shape = Square | Rectangle | Circle;
101 |
102 | function area(shape: Shape) {
103 | switch (shape.kind) {
104 | case "square":
105 | // shape has type Square here
106 | return shape.size * shape.size;
107 | case "rectangle":
108 | // shape has type Rectangle here
109 | return shape.height * shape.width;
110 | case "circle":
111 | // shape has type Circle here
112 | return Math.PI * shape.radius ** 2;
113 | }
114 | }
115 | ```
116 |
117 | TypeScript recognizes that the common property `kind` determines the type here
118 |
119 | Also works with regular if-statements:
120 |
121 | ```typescript
122 | function test(shape: Shape) {
123 | if (shape.kind === "rectangle") {
124 | // shape has type Rectangle here
125 | console.log(shape.height);
126 | }
127 | }
128 | ```
129 |
130 | ### Type guards based on available properties
131 |
132 | Example code (uses the interfaces from the above example):
133 |
134 | ```typescript
135 | function test(shape: Shape) {
136 | if ("radius" in shape) {
137 | // shape has type Circle here
138 | }
139 | }
140 | ```
141 |
142 | ## User-defined type guards
143 |
144 | You can also define your own type guards that perform the type check at runtime by looking at certain properties of the object you receive
145 |
146 | ```typescript
147 | interface Message {
148 | messageType: string;
149 | }
150 |
151 | interface UserMessage extends Message {
152 | messageType: "user";
153 | userId: number;
154 | }
155 |
156 | interface OrderMessage extends Message {
157 | messageType: "order";
158 | orderId: number;
159 | }
160 |
161 | function isMessage(arg: any): arg is Message {
162 | return typeof arg.messageType === "string";
163 | }
164 |
165 | function isUserMessage(arg: Message): arg is UserMessage {
166 | return arg.messageType === "user";
167 | }
168 |
169 | function isOrderMessage(arg: Message): arg is OrderMessage {
170 | return arg.messageType === "order";
171 | }
172 |
173 | function test(input: object) {
174 | console.log(input.messageType); // compiler error
175 |
176 | if (isMessage(input)) {
177 | // input has type Message here
178 |
179 | console.log(input.messageType);
180 | console.log(input.userId); // compiler error
181 | console.log(input.orderId); // compiler error
182 |
183 | if (isUserMessage(input)) {
184 | // input has type UserMessage here
185 | console.log(input.userId);
186 | } else if (isOrderMessage(input)) {
187 | // input has type OrderMessage here
188 | console.log(input.orderId);
189 | }
190 | }
191 | }
192 | ```
193 |
194 | ## Resources
195 |
196 | - [Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
197 | - [Unions and Intersection Types](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html)
198 |
--------------------------------------------------------------------------------