Describes the relevant requirements and the driving forces that software architects and development team must consider.
Egon is a modeling tool that implements the notation and syntactical rules of Domain Storytelling. It supports its users when modeling in workshops and sharing workshop results.
- Users: Intended users are are already familiar with Domain Storytelling. They do not require a technical background.
- Developers: Egon was initiated and developed by German software company WPS - Workplace Solutions GmbH. All active developers are employees of this company. Most developers are also users of Egon.
- Contributors: Programmers from all around the world can contribute code to Egon via pull requests. We assume that contributors are also users of Egon.
Top quality goals are:
- Functional suitability: System provides functions that meets stated or implied needs.
- Operability: System can be understood, learned, used, and is attractive to its users.
Any requirement that constrains software architects in their freedom of design and implementation decisions or decision about the development process.
Constraint | Reason |
---|---|
runs in browser | users do not need to install anything on their machine; developers can deploy new versions easily |
distributed under liberal open source license | increases adoption by providing Egon free of charge (even for "commercial" use), without risk of vendor lock-in; while Egon is open source, the domain stories created with Egon do not fall under an open source license |
no registration or log-in required | increases adoption; ease of use; avoids security problems; lowers maintenance effort |
no centralized storage | avoids security problems; lowers maintenance effort |
can by hosted locally or within company network | avoids vendor lock-in; increases adoption by companies |
when run locally: can be used without internet connection | increases robustness |
System scope and context delimits the system from all its communication partners. It thereby specifies the external interfaces.
The following C4 System Context Diagram shows Egon.io as black box with its communication partners (neighboring systems and users).
flowchart TD
User["User
[Person]"]
Egon["Egon
[Software System]"]
Local["Local File System
[Software System]"]
Remote["Remote File System
[Software System]"]
User-- "models, exports, and imports\nDomain Stories using" -->Egon
User-- "configures icon\nsets using" -->Egon
Egon-- "imports Domain Stories,\n icon sets, icons from" -->Local
Egon-- "exports Domain Stories,\n icon sets, images to" -->Local
Egon-- "imports Domain\nStories from" -->Remote
classDef focusSystem fill:#1168bd,stroke:#0b4884,color:#ffffff
classDef supportingSystem fill:#666,stroke:#0b4884,color:#ffffff
classDef person fill:#08427b,stroke:#052e56,color:#ffffff
class User person
class Egon focusSystem
class Local,Remote supportingSystem
A short summary and explanation of the fundamental decisions and solution strategies, that shape the system’s architecture.
Domain Storytelling is a modeling language and we wanted to build a proper modeling tool that implements the notation and grammar. We assumed that it was easier to use a modeling framework rather than building this from scratch or using a diagramming library that only knows about boxes and arrows. Hence, we searched for a modeling framework that...
- was flexible enough to support the Domain Storytelling modeling language
- and fulfilled the architectural constraints.
bpmn-js checked all the boxes. It is a JavaScript modeling library for the BPMN language. For version 1.x.x. of Egon, we replaced BPMN with the Domain Storytelling modeling language and stayed close to the tech stack used by bpmn-js: JavaScript as programming language, tools for building and testing, etc.
However, the decision for using bpmn-js had tradeoffs: For some features, Egon developers had to dive deep into the inner workings of bpmn-js and work around the framework's behavior. At the same time, bpmn-js offers a lot of features that are not relevant for Domain Storytelling.
The decision for using bpmn-js was revisited several times, but until now, we are not aware of an alternative modeling framework that fulfilles the architectural constraints.
After a few years of development, we had built features that had little to no connection to the bpmn-js framework. However, the architecture made it difficult to distinguish...
- code that deals with core modeling activities and requires knowledge of bpmn-js
- and code that is independent of bpmn-js
We wanted to flatten the learning curve for new developers by better separating Egon and bpmn-js. This went hand in hand with migration to a different tech stack (Typescript and Angular, see below) that helped us to better express the intended architecture.
Since all developers share a common background (see Stakeholders) which includes experience with Typescript and Angular, we decided to migrate most of our code to this tech stack. This lowered the learning curve for new developers, enabling them to work on new features without detailed knowledge of bpmn-js.
The result of this migration is Egon v2.x.x
Users of Egon facilitate Domain Storytelling workshops by modeling the participant's domain stories. They are supposed to share their screen with the participants so that everyone can see how the domain story evolves. In this setting, collaborative editing by multiple users is not relevant.
We assume that a users prefer to model with devices that have a keyboard and mouse/touch pad rather than on touch devices. Hence, touch support was not a requirement when selecting the framework.
The building block view shows the static decomposition of the system into building blocks (modules, components, subsystems, classes, interfaces, packages, libraries, frameworks, layers, partitions, tiers, functions, macros, operations, data structures, …) as well as their dependencies (relationships, associations, …).
Since there is no backend and only one frontend application, the overall architecture is very simple – it consists of just one building block (in C4: container). Here it is depicted as C4 container diagram:
flowchart TD
User["User
[Person]"]
Egon["Web Application
[Container: Typescript, JavaScript, and Angular]"]
Local["Local File System
[Software System]"]
Remote["Remote File System
[Software System]"]
User-- "models, exports, and imports\nDomain Stories using" -->Egon
User-- "configures icon\nsets using" -->Egon
Egon-- "imports Domain Stories,\n icon sets, icons from" -->Local
Egon-- "exports Domain Stories,\n icon sets, images to" -->Local
Egon-- "imports Domain\nStories from" -->Remote
classDef container fill:#1168bd,stroke:#0b4884,color:#ffffff
classDef person fill:#08427b,stroke:#052e56,color:#ffffff
classDef supportingSystem fill:#666,stroke:#0b4884,color:#ffffff
class User person
class Egon container
class Local,Remote supportingSystem
subgraph EgonSystem[Egon]
Egon
end
style EgonSystem fill:none,stroke:#CCC,stroke-width:2px,color:#CCC,stroke-dasharray: 5 5
On the top level, the web app is organized into a layered architecture. Some layers contain – among other things – Angular modules and components which themselves are structured into technical layers.
flowchart TD
Startup["Startup
[Layer]
initializes the application
"]
Workbench["Workbench
[Layer]
a home for modeling tools and settings
"]
Tools["Tools
[Layer]
contains modeling tools
"]
Domain["Domain
[Layer]
...
"]
Utils["Utils
[Layer]
a collection of little utilities
"]
classDef layer fill:#1168bd,stroke:#0b4884,color:#ffffff
class Startup,Workbench,Tools,Domain,Utils layer
Startup-- "initializes" -->Workbench & Tools
Workbench-- "starts" -->Tools
Tools-- "uses" -->Domain & Utils
The folder structure resembles the layered architecture:
app
=> Startup layerworkbench
=> Workbench layertools
=> Tools layerdomain
=> Domain layerutils
=> Utils layer
The architecture rules are enforced with ArchLint and can be checked by running npm run archlint.
All arrows represent dependencies.
flowchart TD
app["app
[Angular Component]"]
header["header
[Angular Component]"]
settings["settings
[Angular Component]"]
info["info dialog
[Angular Component]"]
as-drafts["autosave-drafts
[Angular Component]"]
as-options["autosave-options
[Angular Component]"]
as-settings["autosave-settings
[Angular Component]"]
details-list["details-list
[Angular Component]"]
classDef component fill:#1168bd,stroke:#0b4884,color:#ffffff
class app,header,settings,info,as-drafts,as-options,as-settings,details-list component
app---->header & settings
subgraph as-module["autosave module"]
as-drafts
as-options
as-settings
end
subgraph export-module["export module"]
end
subgraph import-module["import module"]
end
subgraph is-module["icon-set configuration module"]
details-list
end
subgraph ld-module["label dictionary module"]
end
subgraph modeler-module["label dictionary module"]
end
subgraph title-module["label dictionary module"]
end
classDef module fill:none,stroke:#BBB stroke-width:2px,color:#BBB,stroke-dasharray: 5 5
class as-module,export-module,is-module,import-module,ld-module,modeler-module,title-module module
subgraph startup["startup layer"]
app
end
subgraph workbench["workbench layer"]
header
settings
end
subgraph tools["tools layer"]
as-module
export-module
import-module
is-module
ld-module
modeler-module
title-module
end
subgraph domain["domain layer"]
info
end
classDef layer fill:none,stroke:#CCC,stroke-width:2px,color:#CCC,stroke-dasharray: 5 5
class startup,workbench,tools,domain layer
TODO: complete diagram
TODO: Show vertical slices and usage of bmpn-js. The folder structure resembles the vertical slices.
This section is based on the bpmn-js documentation and aims at giving a brief introduction to the library. This should be helpful when working on the modeler
tool.
bpmn-js is built on top of diagram-js and bpmn-moddle. bpmn-js ties both together and provides the palette and the context pad.
The canvas contains graphical elements of different types (shape, label, connection, possibly more). Thereby it ties both the BPMN elements and the graphical elements together. The graphical elements can contains business objects that carry the information that is specific to the modeling language. Business object have types too – e.g., bpmn:ExclusiveGateway
(for the BPMN modeling language ) or domainStory:workObject
(for the Domain Storytelling modeling language). Domain Storytelling's element types for business objects are defined inelementTypes.ts
.
Element positions on the canvas work as shown in this diagram:
quadrantChart
title Coordinate Plane of the bpmn-js Canvas
x-axis "-x" --> "+x"
y-axis "+y" --> "-y"
quadrant-1 "angle: 0° to 90°"
quadrant-2 "angle: 91° to 180°"
quadrant-3 "angle: 181° to 270°"
quadrant-4 "angle: 271° to 359°"
"(x: 0/ y: 0)": [0.5, 0.5]
The runtime view describes concrete behavior and interactions of the system’s building blocks in form of scenarios.
This section is omitted as Egon consists only of one building block.
The deployment view describes the technical infrastructure used to execute your system.
TODO: Maybe document development pipeline here (Github Action builds and pushes to Github Pages, builds Docker container)
Important, expensive, large scale or risky architecture decisions including rationales. With “decisions” we mean selecting one alternative based on given criteria.
Users can configure their icon set and autosave properties. To avoid having to configure everything again the next time a user uses Egon, the user-specific information must be persisted.
Also, autosave creates drafts that must be restorable across browser sessions to recover Domain Stories after a browser crash.
Since Egon runs completely in the browser, we must use local means to persist all user-specific information.
Decision: Use Web Storage (i.e., localStorage
) to persist user-specific information across browser sessions. All popular web browsers implement this standard.
Alternatively, cookies could be used (and in fact were used in earlier Egon versions). Unlike cookies, the storage limit is far larger (at least 5MB).
Since Egon does not use centralized storage (see architectural constraints, users need to export their Domain Stories to their local file system as files.
The most simple way of doing that is to put one domain story into one file and make it self-contained, i.E. include the SVG of the icon set (including custom icons). This makes it easy to share domain stories with other users.
Alternatively a one-to-many relationship (one file containing several Domain Stories) would enable references between Domain Stories. However, this would likely make it necessary to build more features for the export and import tools (e.g., export all stories or just specific ones).
Decision: We choose simplicity over advanced functionality and persist each domain story as one self-contained file.
- JSON as file format
- no separation of model and diagram
- Angular-specific patterns
This section contains all quality requirements as quality tree with scenarios.
TBD
A list of identified technical risks or technical debts, ordered by priority
TBD
Egon uses terminology of Domain Storytelling in the UI and in the code. See Domain Storytelling Website.