diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4dba927..a771f31 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ on: - '*' jobs: - website: + website-ubuntu: runs-on: ubuntu-latest steps: - @@ -48,3 +48,35 @@ jobs: env: PAT_MKDOCS_INSIDERS: ${{ secrets.PAT_MKDOCS_INSIDERS }} run: make --environment-overrides docs-deploy + + website-macos: + runs-on: macos-latest + steps: + - + name: Set up Git repository + uses: actions/checkout@v2.4.0 + with: + fetch-depth: 0 + - + uses: actions/cache@v2 + if: ${{ github.ref == 'refs/heads/main' }} + with: + key: ${{ github.ref }} + path: .cache + - + name: Install all MkDocs dependencies + env: + PAT_MKDOCS_INSIDERS: ${{ secrets.PAT_MKDOCS_INSIDERS }} + run: make --environment-overrides docs-install + - + name: Build Site + if: ${{ github.ref != 'refs/heads/main' }} + env: + PAT_MKDOCS_INSIDERS: ${{ secrets.PAT_MKDOCS_INSIDERS }} + run: make --environment-overrides docs-build + - + name: Deploy Site + if: ${{ github.ref == 'refs/heads/main' }} + env: + PAT_MKDOCS_INSIDERS: ${{ secrets.PAT_MKDOCS_INSIDERS }} + run: make --environment-overrides docs-deploy diff --git a/.tool-versions b/.tool-versions index 49be544..7c66ad9 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,3 @@ python 3.10.2 nodejs 17.4.0 +java openjdk-17 diff --git a/Makefile b/Makefile index 42b8cbd..ceb4eb5 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ docs-install-brew-packages: docs-install-brew brew upgrade libjpeg || brew install libjpeg brew upgrade libpng || brew install libpng brew upgrade zlib || brew install zlib + brew upgrade plantuml || brew install plantuml .PHONY: docs-install-brew ifeq ($(YOUR_OS), Linux) @@ -104,6 +105,8 @@ endif @echo "Install packages via pip:" pip install --upgrade pip pip install --upgrade wheel +# pip install --upgrade plantuml-markdown + pip install --upgrade mkdocs-build-plantuml-plugin pip install --upgrade mkdocs pip install --upgrade mkdocs-localsearch pip install --upgrade mkdocs-include-markdown-plugin diff --git a/docs/concept/concept.md b/docs/concept/concept.md index 7bbf72b..0bdaff7 100644 --- a/docs/concept/concept.md +++ b/docs/concept/concept.md @@ -17,7 +17,6 @@ classDiagram - vocabulary: Vocabulary - stories: Story[] } - link UseCase "../use-case/" UseCase --> UseCase : requires Vocabulary "*" --> "*" Concept Vocabulary "*" --> "*" Term @@ -31,4 +30,9 @@ classDiagram Concept --> Concept : broader Concept --> Term : preferred UseCase --> "1" Vocabulary : use case vocabulary + Persona "1" --o "0..*" Story + link UseCase "../use-case/" + link Story "../story/" + link Concept "../concept/" + link Persona "../persona/" ``` diff --git a/docs/concept/persona.md b/docs/concept/persona.md index 72519d7..37ada5b 100644 --- a/docs/concept/persona.md +++ b/docs/concept/persona.md @@ -1,2 +1,51 @@ # Persona +=== "Business Audience" + + For any given Use Case we need to have a list of all the different types of players. + In the initial stages of the life cycle of a use case it is less relevant whether these players + are called Stakeholders, Actors, Roles, User Types or Systems, we simply need to know what terms the + actual users, the real customer(s) of the use case, are using for them in their daily practice. + + We call them Personas. + + For example, in the use case "Legal Entity Management" you would have Personas like: + + - Auditor + - Data Owner + - Shareholder + - Director + - Signator + - Signator Power Pursuent to Commercial Register + - Board Member + - Legal Council + - Liquidator + - ... + + Many of these Personas are involved in multiple use cases and are grouped together in _persona taxonomies_ + and defined in _ontologies_ with "machine readable meaning" that can be used to let algorithms "understand" + the actual context and act upon it. + +=== "Data & Tech Audience" + + In traditional use case modelling people use the term _Actor_ rather than _Persona_. + The term _Actor_ is also used in a TOGAF Metamodel and combined with the term _Role_ whereby an actor + assumes a role to perform a task. + + The Use Case Tree Method does not make that distinction, primarily to keep things as simple as possible when + capturing requirements --- primarily as [stories](story.md) --- but also because the term Persona combines both + concepts into one whereby: + + - Actors assuming a Role is fully automated, context dependent, model-, rule- and policy-driven + - Personas are [Concepts](concept.md) tied to Ontology-defined Classes that can inherit from other Persona types + - Personas are not just the "users" (or systems) of the use case but also any other party in the related + data-models (or EKG models/ontologies). For instance, your user can have the persona "Legal Entity Maintainer" + but since the legal entity can have a Director as well, the Director is also a Persona, even when that + Director might never be an active user of the system. + + +=== "Model" + +A subset of the model, as a UML Class Diagram, around **Persona**. + +![Context](../diagrams/out/persona-class-diagram.svg#darkable) diff --git a/docs/concept/use-case.md b/docs/concept/use-case.md index 7ece88c..5ac6ec8 100644 --- a/docs/concept/use-case.md +++ b/docs/concept/use-case.md @@ -3,27 +3,33 @@ A Use Case specifies a distinct set of business requirements --- captured as an "executable model" --- resulting in a specific business outcome. +## Process + +Ideas for use cases could come from any person in the organization at any point in time. +We want all these ideas to end up in the organization's Use Case Tree, whether they are viable or not. +If an idea for a given use case is rejected then show the rationale for that to everyone so that everyone can +learn, and we're not wasting any time on that idea again. + +Let people contribute. All knowledge workers, all specialist users, data architects, technical architects, ontologists, +end users, business executives, literally anyone should be allowed to understand: + +- what's our business identity? Our mission and strategy? +- how does that map to our current and future data and technology landscape? +- (without becoming too technical or detailed, we want everyone to be able to chip in) +- how does our "technical debt" fit in? (identify the functionality of our technical debt as use cases in the tree as well) +- how are we going to "rationalise" our current siloed landscape (and technical debt)? +- what are the short and long term priorities? +- what are the milestones and the roadmap? +- which ideas (for use cases) have been proposed, considered approved or rejected and why? + +![Context](../diagrams/out/use-case-development-process.svg#darkable) + ## Life cycle -Use Cases go through a life-cycle of continuous improvement such as:[^1] - -```mermaid -journey - title Use Case Life Cycle - section Plan - Discovery: 5: Business, Analyst - Negotiation: 2: Business, Owner, Analyst - Agreed: 5: Business, Owner - section Build - Implementation: 1: Analyst, Ontologist, Engineer - Acceptance Test: 3: Owner - Delivered: 4: Engineer - section Run - Deployed: 5: DevOps - Decommissioned: 1: DevOps -``` +Each individual Use Case itself goes through a life-cycle of continuous improvement like:[^1] + +![Context](../diagrams/out/use-case-life-cycle.svg#darkable) -[^1]: the life-cycle diagram shown is obviously a simplification ## Key components @@ -65,9 +71,10 @@ the term --- it is not exactly the same, in our Use Case Tree Method: highest levels of these trees a use case can represent a capability domain or a "strategic use case" --- or basically anything that fits well with the business. - at the lowest levels in this tree we would end up with use cases that are much more - like turn-key components for the EKG, 100% reusable delivering "no code"-functionality[^1]. + like turn-key components for the EKG, 100% reusable delivering "no code"-functionality[^2]. -[^1]: [No-code](https://en.wikipedia.org/wiki/No-code_development_platform) or +[^1]: the life-cycle diagram shown is obviously a simplification +[^2]: [No-code](https://en.wikipedia.org/wiki/No-code_development_platform) or [Low-code](https://en.wikipedia.org/wiki/Low-code_development_platform) development allows non-programmers to create applications without hard-wiring business logic with a programming language diff --git a/docs/diagrams/.gitignore b/docs/diagrams/.gitignore new file mode 100644 index 0000000..89f9ac0 --- /dev/null +++ b/docs/diagrams/.gitignore @@ -0,0 +1 @@ +out/ diff --git a/docs/diagrams/include/themes/dark.puml b/docs/diagrams/include/themes/dark.puml new file mode 100644 index 0000000..033420d --- /dev/null +++ b/docs/diagrams/include/themes/dark.puml @@ -0,0 +1,11 @@ +!define BG_MAIN_COLOR #1A618C +!define BG_SECONDARY_COLOR #616768 +!define BG_PACKAGE_COLOR #7a209f +!define BORDER_COLOR #EEEEEE +!define FONT_COLOR #EEEEEE + +skinparam backgroundColor #transparent + +' include the general skinparams for both, light and dark +' to overwrite with the given settings +!include general.puml \ No newline at end of file diff --git a/docs/diagrams/include/themes/general.puml b/docs/diagrams/include/themes/general.puml new file mode 100644 index 0000000..e96e3d4 --- /dev/null +++ b/docs/diagrams/include/themes/general.puml @@ -0,0 +1,159 @@ +!define BORDER_THICKNESS 3 + +skinparam Padding 4 +skinparam RoundCorner 4 +skinparam Shadowing false + +skinparam Default { + 'FontName "Open Sans Semibold" + FontColor FONT_COLOR + FontSize 12 +} + +skinparam Arrow { + Color FONT_COLOR + FontColor FONT_COLOR + FontStyle Bold +} + +skinparam package { + FontColor FONT_COLOR + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR +} +skinparam node { + FontColor FONT_COLOR + BackgroundColor BG_PACKAGE_COLOR + BorderColor BORDER_COLOR +} +skinparam component { + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + FontColor FONT_COLOR + Style uml2 +} + +skinparam database { + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + FontColor FONT_COLOR +} + +skinparam cloud { + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + FontColor FONT_COLOR +} + +skinparam collections { + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + FontColor FONT_COLOR +} +skinparam Control { + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + FontColor FONT_COLOR +} +skinparam Boundary { + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + FontColor FONT_COLOR +} +skinparam Entity { + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + FontColor FONT_COLOR +} +skinparam interface { + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + FontColor FONT_COLOR +} +skinparam SequenceParticipantBorderThickness 3 +skinparam sequence { + ParticipantBackgroundColor BG_MAIN_COLOR + ParticipantBorderColor BORDER_COLOR + ParticipantFontStyle normal + ParticipantFontColor FONT_COLOR + LifeLineBorderColor BORDER_COLOR + LifeLineBackgroundColor BG_MAIN_COLOR + ArrowColor FONT_COLOR + ArrowBorderColor BORDER_COLOR + ArrowFontColor FONT_COLOR + ArrowThickness 3 + ActorBackgroundColor BG_MAIN_COLOR + ActorBorderColor BORDER_COLOR + ActorFontColor FONT_COLOR +} + +' C4 Styling +' ################################## + +skinparam rectangle<> { + StereotypeFontColor FONT_COLOR + FontColor FONT_COLOR + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + BorderThickness BORDER_THICKNESS +} + +skinparam rectangle<> { + StereotypeFontColor FONT_COLOR + FontColor FONT_COLOR + BackgroundColor BG_SECONDARY_COLOR + BorderColor BORDER_COLOR + BorderThickness BORDER_THICKNESS +} + +skinparam rectangle<> { + StereotypeFontColor FONT_COLOR + FontColor FONT_COLOR + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + BorderThickness BORDER_THICKNESS +} + +skinparam rectangle<> { + StereotypeFontColor FONT_COLOR + FontColor FONT_COLOR + BackgroundColor BG_SECONDARY_COLOR + BorderColor BORDER_COLOR + BorderThickness BORDER_THICKNESS +} + +skinparam database<> { + StereotypeFontColor FONT_COLOR + FontColor FONT_COLOR + BackgroundColor BG_MAIN_COLOR + BorderColor BORDER_COLOR + BorderThickness BORDER_THICKNESS +} + +skinparam database<> { + StereotypeFontColor FONT_COLOR + FontColor FONT_COLOR + BackgroundColor BG_SECONDARY_COLOR + BorderColor BORDER_COLOR + BorderThickness BORDER_THICKNESS +} + +skinparam rectangle<> { + Shadowing false + StereotypeFontSize 0 + BackgroundColor BG_PACKAGE_COLOR + StereotypeFontColor FONT_COLOR + FontColor FONT_COLOR + BorderColor BORDER_COLOR + BorderStyle dashed + BorderThickness BORDER_THICKNESS +} +skinparam rectangle<> { + Shadowing false + StereotypeFontSize 14 + BackgroundColor BG_MAIN_COLOR + StereotypeFontColor FONT_COLOR + FontColor FONT_COLOR + BorderColor BORDER_COLOR + BorderThickness BORDER_THICKNESS +} \ No newline at end of file diff --git a/docs/diagrams/include/themes/light.puml b/docs/diagrams/include/themes/light.puml new file mode 100644 index 0000000..3b333cf --- /dev/null +++ b/docs/diagrams/include/themes/light.puml @@ -0,0 +1,11 @@ +!define BG_MAIN_COLOR #66BCF0 +!define BG_SECONDARY_COLOR #B4BCBE +!define BG_PACKAGE_COLOR #eeb291 +!define BORDER_COLOR #444444 +!define FONT_COLOR #444444 + +skinparam backgroundColor #white + +' include the general skinparams for both, light and dark +' to overwrite with the given settings +!include general.puml \ No newline at end of file diff --git a/docs/diagrams/src/persona-class-diagram.puml b/docs/diagrams/src/persona-class-diagram.puml new file mode 100644 index 0000000..6b07c8c --- /dev/null +++ b/docs/diagrams/src/persona-class-diagram.puml @@ -0,0 +1,27 @@ +@startuml + +!include ../include/themes/light.puml + +class Concept { + - type : ConceptType +} +class Concept [[http://plantuml.com{Optional tooltip} This label is printed]] +class UseCase { + - vocabulary: Vocabulary + - stories: Story[] +} +UseCase --> UseCase : requires +Vocabulary "*" --> "*" Concept +Vocabulary "*" --> "*" Term +Story --> "*" Concept : input +Story --> "*" Concept : output +Term --> "1..*" Concept +Concept ---right-> OntologyAxiom +Vocabulary <--> Concept +UseCase --> "1..*" Story +Persona --up-|> Concept +Concept --> Concept : broader +Concept --> Term : preferred +UseCase --> "1" Vocabulary : use case vocabulary +Persona "1" -right-o "0..*" Story +@enduml diff --git a/docs/diagrams/src/use-case-development-process.puml b/docs/diagrams/src/use-case-development-process.puml new file mode 100644 index 0000000..fa7835c --- /dev/null +++ b/docs/diagrams/src/use-case-development-process.puml @@ -0,0 +1,71 @@ +@startuml + +!include ../include/themes/light.puml + +state Plan { + + [*] -down-> Envision + + Envision -down-> Discover + Discover -down-> Assess + Assess -down-> Chart + + Envision: - a shared strategy + Discover: - strategic use cases + Discover: - initial use case tree + Discover: - business knowledge + Discover: - priorities & outcomes + + Assess: - current state + Assess: - required next state + Assess: - maturity (buss/org/data/tech) + + Chart: - viable roadmap + Chart: - business case + Chart: - stakeholder agreement + Chart: - mandate +} + +state Build { + Chart -> Allocate: handover to\ndelivery manager + + Allocate -up-> Implement + + Implement -up-> Test + Test -up-> Verify + Verify -up-> Deliver + ' Verify -> Plan + + Allocate: - budget & team + Implement: - detail the use case + Test: - add test scenarios + Test: - full coverage + Verify: - verify with business + Deliver: - continuously improve + Deliver: - deliver small increments + Deliver: - frequently +} + +state Run { + Deliver -right-> Deploy + Deploy -down-> Operate + Operate -down-> Measure + Measure -down-> Optimize + + Deploy: - as "Infrastructure as Code" + Deploy: - "continuous deployment" + Deploy: - fully automated + + Measure: - performance + Measure: - availability + Measure: - vulnerability + Measure: - business outcome(s) + + Optimize: - structural feedback loop + Optimize: - continuously improve + Optimize: - continuoysly update\n use case tree +} + +Optimize --up--> Plan + +@enduml diff --git a/docs/diagrams/src/use-case-life-cycle.puml b/docs/diagrams/src/use-case-life-cycle.puml new file mode 100644 index 0000000..f5723f2 --- /dev/null +++ b/docs/diagrams/src/use-case-life-cycle.puml @@ -0,0 +1,44 @@ +@startuml + +!include ../include/themes/light.puml + +[*] -> Identified + +Identified -> Defined + +Defined -> Proposed + +Proposed -down-> [*]: Rejected + +Proposed -> Planned + +Planned -> InProgress + +InProgress -> Delivered + +Delivered -> Deployed + +Deployed -> Defined: new version + +Deployed -> Deprecated + +Deprecated -> Decommissioned + +Decommissioned -> [*] + +Identified: - name and description +Identified: - added to use case tree + +Defined: - outcomes +Defined: - personas +Defined: - concepts +Defined: - stories +Defined: - dependencies + +Proposed: - chart phase + +Planned: - on roadmap + +InProgress: - build phase + +@enduml diff --git a/docs/javascript/images_dark.js b/docs/javascript/images_dark.js new file mode 100644 index 0000000..e8e05c6 --- /dev/null +++ b/docs/javascript/images_dark.js @@ -0,0 +1,28 @@ +const paletteSwitcher1 = document.getElementById("__palette_1"); +const paletteSwitcher2 = document.getElementById("__palette_2"); + +paletteSwitcher1.addEventListener("change", function () { + const darkables = document.querySelectorAll('img[src$="darkable"'); + fromDarkToLight(darkables); +}); + +paletteSwitcher2.addEventListener("change", function () { + const darkables = document.querySelectorAll('img[src$="darkable"'); + fromLightToDark(darkables); +}); + +function fromLightToDark(images) { + images.forEach(image => { + const idx = image.src.lastIndexOf('.'); + if (idx > -1) { + const add = "_dark"; + image.src = [image.src.slice(0, idx), add, image.src.slice(idx)].join(''); + } + }); +} + +function fromDarkToLight(images) { + images.forEach(image => { + image.src = image.src.replace("_dark", ""); + }); +} \ No newline at end of file diff --git a/docs/extra/refresh_on_toggle_dark_light.js b/docs/javascript/refresh_on_toggle_dark_light.js similarity index 56% rename from docs/extra/refresh_on_toggle_dark_light.js rename to docs/javascript/refresh_on_toggle_dark_light.js index 293ed00..a5b7fa7 100644 --- a/docs/extra/refresh_on_toggle_dark_light.js +++ b/docs/javascript/refresh_on_toggle_dark_light.js @@ -1,5 +1,5 @@ -var paletteSwitcher1 = document.getElementById("__palette_1"); -var paletteSwitcher2 = document.getElementById("__palette_2"); +const paletteSwitcher1 = document.getElementById("__palette_1"); +const paletteSwitcher2 = document.getElementById("__palette_2"); paletteSwitcher1.addEventListener("change", function () { location.reload(); diff --git a/docs/objective/capture-knowledge.md b/docs/objective/capture-knowledge.md index 5e4cdd6..e45dd2a 100644 --- a/docs/objective/capture-knowledge.md +++ b/docs/objective/capture-knowledge.md @@ -1,5 +1,7 @@ # Capture Knowledge -The Use Case Tree **Provides a "map" of all knowledge, data and +The Use Case Tree **Provides a "map"[^1] of all knowledge, data and functionality** that the EKG provides to the enterprise. Enabling a whole new league of use cases. + +[^1]: See also [Align with Business Strategy: Business Capability Maps](align-with-business-strategy.md) \ No newline at end of file diff --git a/mkdocs.outsiders.yml b/mkdocs.outsiders.yml index 68df61e..24f0e00 100644 --- a/mkdocs.outsiders.yml +++ b/mkdocs.outsiders.yml @@ -10,7 +10,7 @@ plugins: securityLevel: 'loose' extra_javascript: - https://unpkg.com/mermaid/dist/mermaid.min.js - - extra/refresh_on_toggle_dark_light.js + - javascript/refresh_on_toggle_dark_light.js markdown_extensions: - pymdownx.superfences: custom_fences: diff --git a/mkdocs.yml b/mkdocs.yml index c1cdd07..cc984e5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -58,6 +58,8 @@ extra: link: https://www.linkedin.com/company/EKGF - icon: fontawesome/brands/github link: https://github.com/EKGF/use-case-tree-method +extra_javascript: + - "javascript/images_dark.js" plugins: - include-markdown - git-revision-date @@ -70,6 +72,23 @@ plugins: strict: true - macros: module_name: docs/main + - build_plantuml: + render: "server" # or "local" for local rendering + bin_path: "/usr/local/bin/plantuml" # ignored when render: server + server: "http://www.plantuml.com/plantuml" # offical plantuml server + output_format: "svg" # or "png" + diagram_root: "docs/diagrams" # should reside under docs_dir + output_folder: "out" + input_folder: "src" + input_extensions: "" # comma separated list of extensions to parse, by default every file is parsed + theme_enabled: true + theme_folder: "include/themes" + theme_light: "light.puml" + theme_dark: "dark.puml" +# - exclude: +# glob: +# - diagrams/include/C4/* + markdown_extensions: - toc: permalink: true @@ -82,6 +101,7 @@ markdown_extensions: - footnotes - tables - md_in_html + - pymdownx.smartsymbols - pymdownx.snippets: check_paths: true - pymdownx.details