├── .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 | ![Static dependency visualization](_img/Dependency-analysis-tools/static-dependency-visualization.png) 24 | 25 | Example interactively explorable visualizations: [ngrev](https://github.com/mgechev/ngrev) 26 | 27 | ![Interactive dependency visualization](_img/Dependency-analysis-tools/interactive-dependency-visualization.png) 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 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 24 | 25 | 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 | ![Grid](./_img/Grids/grid.png) 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 | ![Grid layout example](./_img/Grids/grid-layout-example.png) 36 | 37 | ([image source](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Grids)) 38 | 39 | ### Holy grail layout 40 | 41 | ![Holy grail layout](./_img/Grids/holy-grail.png) 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 | ![Full bleed layout](./_img/Grids/full-bleed.png) 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 | ![Flex model](./_img/Flexbox/flex-model.png) 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 |
114 | 115 | 118 |
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 | ![Package by feature](_img/Package-by-feature-or-component/package-by-feature.png) 18 | 19 | ![Package by component](_img/Package-by-feature-or-component/package-by-component.png) 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 | ![Reshaped testing pyramid](_img/Package-by-feature-or-component/reshaped-testing-pyramid.png) 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 | 21 | 23 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 62 | 65 | 72 | 76 | 80 | 81 | 85 | 89 | 90 | 91 | 92 | 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 | ![Uncertainty framework](_img/Dealing-with-uncertainty/uncertainty-framework.png) 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 | --------------------------------------------------------------------------------