<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Papers by Draftsman.io]]></title><description><![CDATA[Thought Provoking Papers and a New Found Love for Serverless]]></description><link>https://papers.draftsman.io/</link><image><url>https://papers.draftsman.io/favicon.png</url><title>Papers by Draftsman.io</title><link>https://papers.draftsman.io/</link></image><generator>Ghost 3.42</generator><lastBuildDate>Sat, 18 Apr 2026 09:51:42 GMT</lastBuildDate><atom:link href="https://papers.draftsman.io/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Modeling in Tracepaper: Notifiers]]></title><description><![CDATA[<p>In the previous posts, we modeled and tested <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate">domain behavior</a> and created a trigger to start this behavior via a <a href="https://papers.draftsman.io/modeling-in-tracepaper-commands">command</a>. We mentioned the concept of Notifiers a couple of times with the remark don't worry about it now. We continue the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper series</a> by focusing on what</p>]]></description><link>https://papers.draftsman.io/modeling-in-tracepaper-notifiers/</link><guid isPermaLink="false">6326f3122f8472006ebf4876</guid><category><![CDATA[Modeling in Tracepaper]]></category><category><![CDATA[Notifier]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Thu, 27 Oct 2022 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/10/possessed-photography-tiNCpHudGrw-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/10/possessed-photography-tiNCpHudGrw-unsplash.jpg" alt="Modeling in Tracepaper: Notifiers"><p>In the previous posts, we modeled and tested <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate">domain behavior</a> and created a trigger to start this behavior via a <a href="https://papers.draftsman.io/modeling-in-tracepaper-commands">command</a>. We mentioned the concept of Notifiers a couple of times with the remark don't worry about it now. We continue the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper series</a> by focusing on what are Notifiers and what can we do with them. The <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">concept overview</a> visualizes the scope of this post.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/notifier-blogpost-scope.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/notifier-blogpost-scope.png 600w, https://papers.draftsman.io/content/images/2022/10/notifier-blogpost-scope.png 861w" sizes="(min-width: 720px) 720px"><figcaption>A notifier is triggered by an event. Most commonly by a domain-event but you could very well use an actor-event (command).</figcaption></figure><p>Notifiers are comparable to aggregate behavior because they both represent logic flows, but they do differ drastically.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/Notifier-blog.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers"></figure><p>As you can see in the visualization both execute a flow of logic after receiving a trigger. A trigger is always an event, for the execution it is irrelevant what kind of event.</p><ul><li>Domain-Event is emitted by an Aggregate.</li><li>Actor-Event is published by the API (it is modeled using a <a href="https://papers.draftsman.io/modeling-in-tracepaper-commands/">command</a>)</li></ul><p>There are two key differences:</p><ol><li><strong>State</strong>: An Aggregate has state and the flow of logic has read access to this state. It can manipulate this state by emitting domain events. A Notifier is stateless.</li><li><strong>Connectivity</strong>: An Aggregate has <u>no</u> internet access*. A notifier can connect to the internet and access any API you like. Even the project's API. A notifier doesn't emit domain events, but it could emit actor events with the aid of an API call.</li></ol><p>*You could bypass this limitation by introducing custom code, but you really shouldn't. An aggregate should not be dependent on anything other than triggers and their state. In a future release, we may even <a href="https://pypi.org/project/function-shield/">enforce </a>this.</p><h1 id="endless-possibilities">Endless Possibilities</h1><p>Accessing any API you like opens a world of possibilities. For example, sending an e-mail via <a href="https://aws.amazon.com/ses/">AWS SES</a>. But you are not bound to use AWS services, for example, we send our emails via the <a href="https://documentation.mailgun.com/en/latest/api_reference.html">MailGun API</a>.</p><p>One of the constructs we use a lot in Tracepaper is a read-loop-write. For example, refactoring a subdomain name entails updating the functional keys of the "child" aggregates (<a href="https://papers.draftsman.io/why-we-need-a-keychain/">remember the canonical key concept</a>?)</p><p>So we fetch all child keys with a GraphQL query, loop these keys, and trigger a GraphQL mutation on these elements</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-8.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-8.png 600w, https://papers.draftsman.io/content/images/2022/10/image-8.png 767w" sizes="(min-width: 720px) 720px"><figcaption>The Tracepaper notifiers</figcaption></figure><p>The before-mentioned construct is used for the refactoring and cleanup notifiers. The other notifiers are used to control identity and access management e.g. creating groups when a new workspace is created or adding or removing users from said groups. Sending emails or flushing the content delivery network (CDN) we use for caching the front end.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/Notifier-blog-Page-2.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/Notifier-blog-Page-2.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/Notifier-blog-Page-2.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/10/Notifier-blog-Page-2.png 1600w, https://papers.draftsman.io/content/images/2022/10/Notifier-blog-Page-2.png 1665w" sizes="(min-width: 720px) 720px"><figcaption>Notifiers support different activities (Schedule Event &amp; Loop are not supported yet).&nbsp;</figcaption></figure><h1 id="send-an-email">Send an Email</h1><p>To get back to the <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate/">modeling example</a>. Let's say we want to send a welcome email when somebody opens a new account.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/image-9.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-9.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-9.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/10/image-9.png 1600w, https://papers.draftsman.io/content/images/2022/10/image-9.png 1885w" sizes="(min-width: 720px) 720px"></figure><p>As a core concept, you can find the notifiers tab on the main page. But just like <a href="https://papers.draftsman.io/modeling-in-tracepaper-commands">commands</a>, there is a more convenient way to "attach" a notifier to a domain event using the autofill feature.   </p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/2022-10-09-23-56-41.gif" class="kg-image" alt="Modeling in Tracepaper: Notifiers"></figure><p>I'll break it down for you.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-11.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-11.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-11.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/10/image-11.png 1600w, https://papers.draftsman.io/content/images/2022/10/image-11.png 1897w" sizes="(min-width: 720px) 720px"><figcaption>We navigate to the behavior flow we modeled in a <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate/">previous post</a>.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-12.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-12.png 600w, https://papers.draftsman.io/content/images/2022/10/image-12.png 759w" sizes="(min-width: 720px) 720px"><figcaption>We locate the emit event processor and click the yellow button "Attach Notifier"</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-13.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-13.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-13.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-13.png 1155w" sizes="(min-width: 720px) 720px"><figcaption>The initialize notifier dialog is opened. We picked SendWelcomeEmail as an identifiable name.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-14.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-14.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-14.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-14.png 1155w" sizes="(min-width: 720px) 720px"><figcaption>On the next screen, the flow variables are automatically filled with emailAdress &amp; balance. This is based on the domain event we attach this notifier. We add "emailBody" as an extra flow variable.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-15.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-15.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-15.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-15.png 1147w" sizes="(min-width: 720px) 720px"><figcaption>The next screen contains the trigger configuration. It is automatically filled.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-16.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers"><figcaption>We add our first activity, render a template.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-17.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-17.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-17.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-17.png 1151w" sizes="(min-width: 720px) 720px"><figcaption>Our project doesn't have any templates yet, so we create one by clicking the yellow button.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-18.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-18.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-18.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/10/image-18.png 1600w, https://papers.draftsman.io/content/images/2022/10/image-18.png 1715w" sizes="(min-width: 720px) 720px"><figcaption>We create a simple text-based template. It is a global component, but that is a concept for another post. For now, just a simple sentence with 1 substitution variable {{flow.balance}}. During rendering, this will be replaced by the flow-variable value.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-19.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-19.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-19.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-19.png 1033w" sizes="(min-width: 720px) 720px"><figcaption>Now we can configure the activity by selecting the template to render and selecting the flow-variable to store the rendered result into.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-21.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers"><figcaption>We add another activity, sending an email.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-22.png" class="kg-image" alt="Modeling in Tracepaper: Notifiers" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-22.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-22.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-22.png 1036w" sizes="(min-width: 720px) 720px"><figcaption>I think the send-email configuration is self-explanatory.</figcaption></figure><p>We only covered the basics in this post, but it gives you a pretty good idea what you can do with notifiers.</p><blockquote><em><a href="https://trello.com/b/31IIJ3nL/tracepaper-by-draftsman?filter=label:Notifier">Tracepaper backlog regarding Notifiers.</a></em></blockquote><p>Thank you for reading. Next time we will look into Views.</p>]]></content:encoded></item><item><title><![CDATA[Modeling in Tracepaper: Testing Aggregate Behavior]]></title><description><![CDATA[<p>In the previous posts, we modeled <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate">domain behavior</a> and created a trigger to start this behavior via a <a href="https://papers.draftsman.io/modeling-in-tracepaper-commands">command</a>. We continue the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper series</a> by focusing on the quality aspect. Some of it is already available in Tracepaper. Additionally, we will present some plans for the future. The</p>]]></description><link>https://papers.draftsman.io/modeling-in-tracepaper-testing-aggregate-behavior/</link><guid isPermaLink="false">6338363f1fdcbe006e425b5b</guid><category><![CDATA[Modeling in Tracepaper]]></category><category><![CDATA[Aggregate]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Thu, 20 Oct 2022 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/10/8107539280_5a1faf177f_b.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/10/8107539280_5a1faf177f_b.jpg" alt="Modeling in Tracepaper: Testing Aggregate Behavior"><p>In the previous posts, we modeled <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate">domain behavior</a> and created a trigger to start this behavior via a <a href="https://papers.draftsman.io/modeling-in-tracepaper-commands">command</a>. We continue the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper series</a> by focusing on the quality aspect. Some of it is already available in Tracepaper. Additionally, we will present some plans for the future. The <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">concept overview</a> visualizes the scope of this post.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/modeling-blogpost-scope-aggregate-1.png" class="kg-image" alt="Modeling in Tracepaper: Testing Aggregate Behavior" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/modeling-blogpost-scope-aggregate-1.png 600w, https://papers.draftsman.io/content/images/2022/10/modeling-blogpost-scope-aggregate-1.png 881w" sizes="(min-width: 720px) 720px"></figure><p>Modeling is all fun and games until you break production. We need tests to prevent introducing breaking changes. As an architect, I'm interested in correct test coverage. As an engineer, writing tests is not an energizer for me.</p><h3 id="behavior-flows">Behavior Flows</h3><p>If we look at our <em>behavior flows</em> from a testing perspective, they are fairly simple.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/test-blog.png" class="kg-image" alt="Modeling in Tracepaper: Testing Aggregate Behavior"></figure><p>A message triggers behavior, it may interact with the internal state for validations or extrapolations. And it may result in domain events and state changes.</p><p>And that is how we model our tests, where the flow is considered a black box. We model the intention of the test case by declaring the state and the trigger and asserting that the expected messages are emitted. Optionally we check if the end state meets expectations. Every behavior flow should have at least one test case. This is enforced by the engine, it will reject a flow without test cases.</p><p>How many cases you need depends on the complexity of the flow. In Tracepaper, for example, we have 154 flows and 216 test cases. Most flows have just one test case because the complexity is low. Some flows have up to 5 test cases.</p><p>We have not yet figured out how to do proper test coverage calculation. We could use simple code-line coverage, but it feels lazy. It is more valuable to base coverage on the model:</p><ul><li>did we use all defined triggers?</li><li>did we see all defined events emitted?</li><li>did we see all modeled validation errors?</li></ul><p>We know what we want, but we didn't take the time yet to implement it. It is on our backlog somewhere.</p><h3 id="notifiers">Notifiers</h3><p>Compared to behavior flows, notifiers are a harder concept to test. I did not explain notifiers yet, we will take a look next week. For now, you have to take my word for it. Notifiers interact with (external) APIs, so testing them means we have to figure out how to mock these APIs.</p><p>We don't support tests for notifiers yet, but we use them a lot in Tracepaper (19 of them) and they do important things. Bluntly said, if we break the modeled notifiers Tracepaper is effectively worthless. How do we deal with this? We use a more expensive test method, end-to-end testing.</p><h3 id="test-scenarios">Test Scenarios</h3><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/image-4.png" class="kg-image" alt="Modeling in Tracepaper: Testing Aggregate Behavior" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-4.png 600w, https://papers.draftsman.io/content/images/2022/10/image-4.png 845w" sizes="(min-width: 720px) 720px"></figure><p>We have a concept called test scenarios, essentially a scenario is a sequence of API calls against the generated API. The API is generated and extracted from modeling concepts. So when modeling a scenario, we don't think about the API, we think about domain concepts: commands/behavior/notifier/view. In the background, it leans heavily on track and trace.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/image-5.png" class="kg-image" alt="Modeling in Tracepaper: Testing Aggregate Behavior" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-5.png 600w, https://papers.draftsman.io/content/images/2022/10/image-5.png 984w" sizes="(min-width: 720px) 720px"></figure><p>The scenario must be executed against a deployed version of the application, running these test scenarios is a pipeline responsibility.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/concept-pipelines-Page-2.png" class="kg-image" alt="Modeling in Tracepaper: Testing Aggregate Behavior" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/concept-pipelines-Page-2.png 600w, https://papers.draftsman.io/content/images/2022/10/concept-pipelines-Page-2.png 861w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/image-6.png" class="kg-image" alt="Modeling in Tracepaper: Testing Aggregate Behavior" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-6.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-6.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/10/image-6.png 1600w, https://papers.draftsman.io/content/images/2022/10/image-6.png 1783w" sizes="(min-width: 720px) 720px"></figure><p>We are alpha testing this feature at the moment, when we are happy about it we start adding scenario modeling to Tracepaper and making the extended pipeline available for general use.</p><p>A lot of plans, but what can you do at this moment in Tracepaper?</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/10/image-7.png" class="kg-image" alt="Modeling in Tracepaper: Testing Aggregate Behavior" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-7.png 600w, https://papers.draftsman.io/content/images/2022/10/image-7.png 964w" sizes="(min-width: 720px) 720px"></figure><p>Truth be told, it is fairly limited. Sending in a trigger message and asserting that the expected domain events are emitted. It is very basic but good enough for our beta.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-10.png" class="kg-image" alt="Modeling in Tracepaper: Testing Aggregate Behavior" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-10.png 600w, https://papers.draftsman.io/content/images/2022/10/image-10.png 955w" sizes="(min-width: 720px) 720px"><figcaption>This test will be executed during the "Generate" stage.</figcaption></figure><blockquote><a href="https://trello.com/b/31IIJ3nL/tracepaper-by-draftsman?filter=label:QA">Here is a filter on our backlog</a> so you know what to expect in the coming months.</blockquote><p>Thank you for reading!</p>]]></content:encoded></item><item><title><![CDATA[Modeling in Tracepaper: Commands]]></title><description><![CDATA[<p>We continue the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper series</a> by focusing on the interaction with our write domain. <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate/">Last week we left off with the wish to trigger our behavior flow from the GraphQL API</a>. This write interaction is modeled using commands. The scope of this post is visualized in our <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">concept</a></p>]]></description><link>https://papers.draftsman.io/modeling-in-tracepaper-commands/</link><guid isPermaLink="false">63266920b2284f00686957ea</guid><category><![CDATA[Modeling in Tracepaper]]></category><category><![CDATA[Command]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Thu, 13 Oct 2022 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1524741978410-350ba91a70d7.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1524741978410-350ba91a70d7.jpg" alt="Modeling in Tracepaper: Commands"><p>We continue the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper series</a> by focusing on the interaction with our write domain. <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate/">Last week we left off with the wish to trigger our behavior flow from the GraphQL API</a>. This write interaction is modeled using commands. The scope of this post is visualized in our <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">concept overview</a>.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/modeling-blogpost-scope-command.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/modeling-blogpost-scope-command.png 600w, https://papers.draftsman.io/content/images/2022/09/modeling-blogpost-scope-command.png 881w" sizes="(min-width: 720px) 720px"></figure><p>In IT, a command is a message just like an event. The two differ subtly.<br>1. An event is a message that represents that "something" <strong>has happened</strong>.<br>2. A command is a message signaling that we <strong>want</strong> "something" to happen.</p><blockquote>A command is a wish, and an event is a fact. </blockquote><p>We made a conscious choice to use events only to trigger behavior-flows or notifiers. The reason is quite crude, if we only have to handle events we can keep the cognitive complexity of our modeling tool (Tracepaper) in check.</p><blockquote>If you are unfamiliar with GraphQL, <a href="https://pragmaticreviews.com/what-is-graphql-learn-it-in-5-minutes/">this post</a> describes the key concepts in a nutshell. It also features a <a href="https://www.youtube.com/watch?v=wfBeEn8d-8A&amp;t=284s">5 minute video</a> if you prefere an audio visual medium.</blockquote><p>We gave the write side of the API (GraphQL Mutations) 2 responsibilities:<br>1. Convert a command into an event. "OpenAccount" becomes "OpenAccountRequested", it does sound silly but it does effectively convert a <em>wish</em> into a <em>fact</em>. Of course, it may happen that the domain is not capable of processing the event. But that does not change the fact that somebody requested it.<br>2. Convert the synchronous API call into an asynchronous message. </p><p>The client issued a command however, this means they are probably interested in knowing if the processing was successful or not. To facilitate this, the API will return a correlation ID in case the command is accepted. The client can use this identifier to query or subscribe to the <em>track and trace</em> functionality. You may have noticed in our <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate-part-1/">previous post</a> that after every form submission we see a stream of events that have happened in the Tracepaper domain. This is a subscription to <em>track &amp; trace</em>. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/09/image-12.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-12.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-12.png 1000w, https://papers.draftsman.io/content/images/2022/09/image-12.png 1166w" sizes="(min-width: 720px) 720px"><figcaption>Track &amp; Trace output</figcaption></figure><p>It is not necessary perse to show these trace events in our user interface, we do show them however and the reason is two-fold.<br>1. It gives insight into how our generated applications cope with asynchronicity and how we model our domain.<br>2. I like to see that something is happening after I press a button.</p><h2 id="modeling-a-command">Modeling a Command</h2><p>We need to model two things when modeling a command. <br>1. The message structure.<br>2. The API structure and access management.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-13.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-13.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-13.png 1000w, https://papers.draftsman.io/content/images/2022/09/image-13.png 1388w" sizes="(min-width: 720px) 720px"></figure><p>Commands are a core concept and therefore you can navigate to them from the main project screen. A command is thus not bound to another domain concept, and it is perfectly possible to let multiple aggregates and notifiers react to a single command. Remember we convert the command to an event as soon as possible.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-14.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-14.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-14.png 1000w, https://papers.draftsman.io/content/images/2022/09/image-14.png 1161w" sizes="(min-width: 720px) 720px"></figure><p>You can see that the first fields are meant for modeling the API structure. The <a href="https://graphql-rules.com/rules/mutation-namespaces">GraphQL Namespace</a>s are used to logically group commands together to increase the readability of the API contract. Namespaces can be nested by separating them with dots.<br>The GraphQL method name is the actual method in that namespace, those values should be unique together. We generate the command name from those two fields. And in the backend we generate the Event name from the command name:<br>GraphQL Namespace:		Subdomain.Aggregate<br>GraphQL Method name:	create<br>Command Name:				CreateSubdomainAggregate<br>Event Name:						CreateSubdomainAggregateRequested</p><p>We can select an authentication method, the default is <em>authenticated</em>, meaning that the user just needs to be signed in. We have 2 other options (there is secret option 3, anonymous access, but this is not yet enabled):<br>Role-based requires the user to have a specific role, this one is used a lot in Tracepaper.<br>User-based: requires a specific message field to be equal to the signed-in user name. For example, to make sure that only the user itself can mutate, let's say, their profile aggregate instance. The engine has another mechanism to ensure this, but unfortunately, this is not yet supported by Tracepaper (at the moment of writing, check this <a href="https://trello.com/c/iZyhk4zI/23-command-auto-fill">refinement task</a> for the actual state).</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-15.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-15.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-15.png 1000w, https://papers.draftsman.io/content/images/2022/09/image-15.png 1165w" sizes="(min-width: 720px) 720px"></figure><p>The command input fields are used to model the message structure, they represent a JSON structure. We do allow 1 level nesting (Hence the 'NestedString' type), and they are always used for collections. The message structure for this command (naturally, this form is backed by a command that uses the same semantics) looks something like this:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-17.png" class="kg-image" alt="Modeling in Tracepaper: Commands"></figure><p>If we would submit this form, the actual JSON structure that is sent to the API looks like this:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-18.png" class="kg-image" alt="Modeling in Tracepaper: Commands"></figure><p>This is simplified actually because I don't want to bore you with the nitty-gritty details. But here is a screenshot from the actual API structure:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-20.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-20.png 600w, https://papers.draftsman.io/content/images/2022/09/image-20.png 838w" sizes="(min-width: 720px) 720px"></figure><p>We now know how commands are used and modeled, and we know that they are not necessarily bound to one behavior flow or notifier. But you can imagine that most of the time we model specific commands to trigger specific behavior. With that in mind, there is a more convenient way for modeling commands using the best-effort autofill feature. And to utilize this we initialize the command modeling from the context of modeling a trigger for the <a href="https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate-part-1/">behavior flow</a>.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/2022-09-22-01-13-38.gif" class="kg-image" alt="Modeling in Tracepaper: Commands"></figure><p>Let's look at it step by step:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image.png" class="kg-image" alt="Modeling in Tracepaper: Commands"><figcaption>We start by opening the "ad trigger" wizard in the behavior flow view.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-1.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-1.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-1.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-1.png 1443w" sizes="(min-width: 720px) 720px"><figcaption>To add a new command to the project, we click the yellow button.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-2.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-2.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-2.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-2.png 1440w" sizes="(min-width: 720px) 720px"><figcaption>We see the familiar "Initialize Command" view. It is prefilled based on the behavior-flow context. The prefilled values are a mere educated guess. Check everything and submit the form.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/10/image-3.png" class="kg-image" alt="Modeling in Tracepaper: Commands" srcset="https://papers.draftsman.io/content/images/size/w600/2022/10/image-3.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/10/image-3.png 1000w, https://papers.draftsman.io/content/images/2022/10/image-3.png 1441w" sizes="(min-width: 720px) 720px"><figcaption>After the mutation, the add trigger view is reopened. As you can see the just modeled event "OpenAccountingAccountRequested" is pre-selected, and the field-flowvar mapping is prepopulated. We inspect if the prefilling mirror our intentions and submit the form.</figcaption></figure><p>We are done, we created a trigger for our behavior flow that is accessible via the generated API. Before we can show the API, we have to build the code, and we can't build the code before we have tests, a repository, and a pipeline.</p><p>One of the curses of writing is I'm bound to provide a linear flow of information while the subject is more of a graph. So for now, to protect my linear flow, let's focus on the modeling. We will look at pipelines and delivery after this <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">series</a> is done.</p><blockquote>Just like the Aggregate, the Command Concept has more features than are available in Tracepaper at this moment. <a href="https://trello.com/b/31IIJ3nL/tracepaper-by-draftsman?filter=label:Command,member:none,mode:and">Here is a filter on our backlog</a> to get a feeling of what to expect in the coming months.</blockquote><p>This is a good time for a break, next time we will model a test for an Aggregate Behavior-Flow. This post was particularly hard to write, I think because the Command concept is a pretty hefty abstraction, it does quite a lot. A piece of advice I give to all interns and fresh architects.</p><blockquote>Just because it was hard to write doesn't mean it should be hard to read. If your audience doesn't understand it, you failed.</blockquote><p>And with that in mind, looking at this blog post, I may have failed this time. Thank you for reading, if you have feedback <a href="mailto:papers@draftsman.io">let me know</a>.</p>]]></content:encoded></item><item><title><![CDATA[Modeling in Tracepaper: The Aggregate]]></title><description><![CDATA[<p>We continue the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper series</a> by focusing on the hearth of our application. The Domain logic is encapsulated in aggregates. The scope of this post is visualized in our <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">concept overview</a>.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/modeling-blogpost-scope-aggregate.png" class="kg-image" alt srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/modeling-blogpost-scope-aggregate.png 600w, https://papers.draftsman.io/content/images/2022/09/modeling-blogpost-scope-aggregate.png 881w" sizes="(min-width: 720px) 720px"></figure><p>What is an Aggregate? An aggregate is a concept borrowed from <a href="https://papers.draftsman.io/domain-driven-design/">Domain Driven Design</a>. We used 3</p>]]></description><link>https://papers.draftsman.io/modeling-in-tracepaper-the-aggregate/</link><guid isPermaLink="false">6323959ab4d16e0063fcd8ee</guid><category><![CDATA[Modeling in Tracepaper]]></category><category><![CDATA[Aggregate]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Thu, 06 Oct 2022 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1621713306880-4acffab99659--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1621713306880-4acffab99659--1-.jpg" alt="Modeling in Tracepaper: The Aggregate"><p>We continue the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper series</a> by focusing on the hearth of our application. The Domain logic is encapsulated in aggregates. The scope of this post is visualized in our <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">concept overview</a>.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/modeling-blogpost-scope-aggregate.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/modeling-blogpost-scope-aggregate.png 600w, https://papers.draftsman.io/content/images/2022/09/modeling-blogpost-scope-aggregate.png 881w" sizes="(min-width: 720px) 720px"></figure><p>What is an Aggregate? An aggregate is a concept borrowed from <a href="https://papers.draftsman.io/domain-driven-design/">Domain Driven Design</a>. We used 3 core concepts regarding the aggregate:<br>1. An aggregate instance contains an identity and holds an internal state.<br>2. An aggregate defines a transactional boundary. This means any changes to the aggregate will either all succeed or none will succeed.<br>3. An aggregate represents a domain concept.<br>It is quite literally an aggregation of stateful behavior to represent a domain concept.  </p><p>A commonly used tactic is to model an aggregate as a cluster of associated entities and value objects treated as a unit for the purpose of data changes. Data changes are dictated by rich domain behavior, unlike CRUD-style applications.<br>At Draftsman, we use an alternative tactic for state persistence and manipulation, <a href="https://martinfowler.com/eaaDev/EventSourcing.html">Event Sourcing</a>.</p><p>In short, an aggregate in our modeling tool Tracepaper will contain:<br>1. a definition for the state, modeled as aggregate attributes.<br>2. domain event definitions, a domain event may mutate aggregate attributes (among other things.)<br>3. Behavior Flows, a behavior flow is a sequence of logic functions, triggered by an event, and may result in the publication of domain events. </p><p>An aggregate can only interact with the outside world by receiving and publishing events. For example, an aggregate can't use API calls to fetch data or send a mutation to another aggregate. All data needed for the behavior flow must be encapsulated in the trigger event, subsequently, other aggregates can subscribe to the event stream. </p><p>We do have a concept of Notifiers that are able to interact with the outside world. Just as an aggregate it is triggered by an event, whereafter it can orchestrate API calls to other systems or the application API itself. Unlike an aggregate, a notifier does not hold any state. But this is a subject for another post.</p><h2 id="the-subdomain">The Subdomain</h2><p> An aggregate is not free-floating in our domain, in Tracepaper we support a concept called Subdomain that acts as a cluster of related aggregates. A subdomain is a <a href="https://www.martinfowler.com/bliki/BoundedContext.html">bounded context</a> within our domain. So before we can start modeling an aggregate, we have to initialize a subdomain.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/sub-domain.gif" class="kg-image" alt="Modeling in Tracepaper: The Aggregate"></figure><h2 id="the-aggregate">The Aggregate</h2><p>Let's say we have a subdomain accounting and we want to model a concept <em>Account </em>that is used to store the account balance. It has behavior for:<br>1. Opening an account.<br>2. Deposit into the account.<br>3. Withdrawal from the account.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/2022-09-18-00-19-32.gif" class="kg-image" alt="Modeling in Tracepaper: The Aggregate"></figure><p>We start with an empty aggregate. The first thing to do is to add a state definition.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/aggregate-attributes-2.gif" class="kg-image" alt="Modeling in Tracepaper: The Aggregate"></figure><p>Our state definition is very simple, but could definitely be more complex. The next thing to do is start modeling behavior, let's start with the behavior to "Open an account". Let's say we have an additional requirement when opening an account that we will reward everyone with a 10-credit addition to their balance as a welcome gift. With this in mind, it is important that the mentioned behavior is only applicable on non-existing accounts, read, and can only run during aggregate-instance creation.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/2022-09-18-00-38-35.gif" class="kg-image" alt="Modeling in Tracepaper: The Aggregate"></figure><p> We have initialized a behavior flow. A behavior flow is a chain of processors that together define the behavior. We have access to the internal state of the aggregate, although this is limited to read-only. So we can't manipulate the internal state, so let's create some flow variables that we can use as temporary storage.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/2022-09-18-00-40-22.gif" class="kg-image" alt="Modeling in Tracepaper: The Aggregate"></figure><p>Tracepaper provides "best effort" auto-filling fields. It saves you some typing, but you are not absolved from thinking... double check everything.</p><p>A behavior flow is always started from a trigger, a trigger is always an event. We have 2 types of events in our domain.<br>1. Domain-Events, emitted by aggregates. These will be introduced in this post.<br>2. Actor-Events, these are triggered by commands and can be triggered via an API call. An actor event always follows the "{CommandName}Requested" naming semantic.</p><p>For this flow we want to use the second type of event, this means we have to model a command. Modeling the command is a subject for another post. So for now, let us just assume that the flow variables <em>emailAdress </em>and <em>balance </em>are filled at the start of the flow with aid of the trigger mapping. </p><p>We skip ahead to the processors, here we can model the requirement to add the 10-credit gift. We do this by adding a "set-variable" processor.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/2022-09-18-01-18-26.gif" class="kg-image" alt="Modeling in Tracepaper: The Aggregate"></figure><p>We selected "balance" as a target and provided the expression "flow.balance + 10". The expression is evaluated as python, <a href="https://papers.draftsman.io/we-love-python/">because that is the language we selected for our applications</a>. When you generate source code you will find a line:</p><blockquote>flow.balance = flow.balance + 10</blockquote><p> We stated that you have access to the internal state of the aggregate, but issuing the next statement is not gonna do it.</p><blockquote>flow.entity.balance = flow.balance</blockquote><p>This statement will execute successfully, but it won't be persisted. To update the internal-state we have to emit a domain-event. </p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-3.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-3.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-3.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/09/image-3.png 1600w, https://papers.draftsman.io/content/images/2022/09/image-3.png 1659w" sizes="(min-width: 720px) 720px"></figure><p>A domain event is an attribute of the aggregate and could be emitted from multiple behavior flows, it is not bounded to a specific behavior flow. This means we could create one from the aggregate screen. It is, however, more convenient to create one from within our flow. This does not change the positioning of the event, it is still bounded to the aggregate, but we will be supported by the "best effort" autofill functionality.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/2022-09-18-01-39-14.gif" class="kg-image" alt="Modeling in Tracepaper: The Aggregate"></figure><p>A little side step, maybe you noticed that I had to refresh the page during the demo. The thing is, we have an event-based architecture. Even the communication between the front-end and back-end is a mix of synchronous and asynchronous communication. This means everything is eventually consistent.<br>In the backend, we have something called the <a href="https://microservices.io/patterns/data/transactional-outbox.html">transactional outbox</a> and various retries to protect us from missing events. The front-end, however, may sometimes miss an event, meaning that your projection is not consistent with the application state. Luckily we can just refresh the page with F5. Most of the time this will fix the issue. If not, you could click  "Tracepaper" in the upper left corner this will ignore any cached data.</p><p>A lot happening on the screen, let's break it down.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-4.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-4.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-4.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/09/image-4.png 1600w, https://papers.draftsman.io/content/images/2022/09/image-4.png 1905w" sizes="(min-width: 720px) 720px"></figure><p><strong>The first thing we did</strong> is model a domain event. A domain event has an internal name (Opened) that is unique within the aggregate and an external name (AccountingAccountOpened) that is unique within the domain. <br>It has fields, and those are the attributes that are persisted in the event log. There is also a handler-mapping. The handler-mapping defines how the event is applied to the aggregate... It is a setter.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-5.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-5.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-5.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/09/image-5.png 1600w, https://papers.draftsman.io/content/images/2022/09/image-5.png 1894w" sizes="(min-width: 720px) 720px"></figure><p>The event is added to the aggregate view, and from here you could edit it.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-6.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-6.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-6.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/09/image-6.png 1600w, https://papers.draftsman.io/content/images/2022/09/image-6.png 1926w" sizes="(min-width: 720px) 720px"></figure><p>You can choose to edit only the mappings.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-7.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-7.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-7.png 1000w, https://papers.draftsman.io/content/images/2022/09/image-7.png 1212w" sizes="(min-width: 720px) 720px"></figure><p>Or you could edit the fields and the mappings. Let's say we change the balance from Int to Float.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-9.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-9.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-9.png 1000w, https://papers.draftsman.io/content/images/2022/09/image-9.png 1175w" sizes="(min-width: 720px) 720px"></figure><p>This will result in a new event version to ensure backward compatibility, events are persisted after all and you may already have events in your log when you decide an additional field is needed in the event. We don't want our software to crash because we have trouble replaying the event log to determine the state.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-11.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-11.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-11.png 1000w, https://papers.draftsman.io/content/images/2022/09/image-11.png 1200w" sizes="(min-width: 720px) 720px"></figure><h3 id="emiting-the-domain-event">Emiting the Domain Event</h3><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image-10.png" class="kg-image" alt="Modeling in Tracepaper: The Aggregate" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image-10.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image-10.png 1000w, https://papers.draftsman.io/content/images/2022/09/image-10.png 1175w" sizes="(min-width: 720px) 720px"></figure><p><strong>The second thing we did</strong> was model the emit-event processor. It is pretty straightforward. We select the event we want to emit (AccountinAccountOpened) and we map flow variables to event fields. This is best effort auto-filled, but at this point, my browser became out of sync and needed a page refresh.</p><blockquote><a href="https://trello.com/b/31IIJ3nL/tracepaper-by-draftsman?filter=label:Aggregate">Tracepaper backlog regarding the Aggregate.</a></blockquote><p>A good time for a break. The only 2 things left for this behavior flow are a trigger and a test. As mentioned, we want to trigger from a command and that deserves a separate post. Modeling the test without a trigger is not possible, so this has to wait. Thnx for reading, until next time.</p><p></p>]]></content:encoded></item><item><title><![CDATA[How we caved and created a roadmap]]></title><description><![CDATA[<p>In June 2021 I wrote a <a href="https://papers.draftsman.io/why-we-dont-have-a-roadmap/">post proclaiming that we don't have a roadmap</a> and that we don't need it. And the argument <em><strong>we build what we need only when we need it</strong></em> still holds... Only for the engine though.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/HLD-blog-Page-2.png" class="kg-image" alt></figure><!--kg-card-begin: markdown--><p>If we take a look at an <a href="https://papers.draftsman.io/the-thought-behind-tracepaper/">abstract design</a>.</p>
<ol>
<li><strong><a href="https://learning.tracepaper.draftsman.io/">Tracepaper</a></strong></li></ol>]]></description><link>https://papers.draftsman.io/okay-we-do-have-a-roadmap/</link><guid isPermaLink="false">6321000589cc920069ee2d7d</guid><category><![CDATA[way-of-working]]></category><category><![CDATA[About Draftsman]]></category><category><![CDATA[general]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Thu, 29 Sep 2022 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1590103514966-5e2a11c13e21.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1590103514966-5e2a11c13e21.jpg" alt="How we caved and created a roadmap"><p>In June 2021 I wrote a <a href="https://papers.draftsman.io/why-we-dont-have-a-roadmap/">post proclaiming that we don't have a roadmap</a> and that we don't need it. And the argument <em><strong>we build what we need only when we need it</strong></em> still holds... Only for the engine though.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/HLD-blog-Page-2.png" class="kg-image" alt="How we caved and created a roadmap"></figure><!--kg-card-begin: markdown--><p>If we take a look at an <a href="https://papers.draftsman.io/the-thought-behind-tracepaper/">abstract design</a>.</p>
<ol>
<li><strong><a href="https://learning.tracepaper.draftsman.io/">Tracepaper</a></strong> is our modeling studio, a form-based visual tool to map out your application domain.</li>
<li>Tracepaper will export a <strong>technical model</strong>, this model is XML based in what we call <em>Draftsman Modeling Language</em>.</li>
<li>The <strong>Draftsman Engine</strong> converts this technical model into code.</li>
<li>The generated code is stored in a <strong>GitHub</strong> repository.</li>
<li>An <strong>AWS CodePipeline</strong> will build and deploy the application.</li>
</ol>
<!--kg-card-end: markdown--><p>The engine has one function, convert the technical model into code. It is literally a stack of enablers on top of enablers. Mapping concepts to implementations. For example, we need the concept of <strong>state. </strong>We decided to use <a href="https://martinfowler.com/eaaDev/EventSourcing.html">Event Sourcing</a> for maximum flexibility. We design XML structures to model events and event handlers (we sometimes call them glorified setters). And we implement code that converts the designed XML structure into Python code and <a href="https://www.youtube.com/watch?v=Omppm_YUG2g">Cloudformation magic</a>. </p><p>That's it, it doesn't do anything unless you feed it some specific XML. And that is what we did, we started modeling the Tracepaper application by writing the XML by hand. And that is how the engine grew. During the modeling of Tracepaper, we encounter missing concepts (querying, integrations to external APIs, event-chain tracing, and many more.) And that is how the stack of enablers grew. We built what we need when we need it. </p><p>In the generator report you can see the concepts mentioned, how many lines XML are used to describe the model and what is generated. In the screenshot you can see the generator report for the application that is modelled during the <a href="https://learning.tracepaper.draftsman.io/">tutorial</a>.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/09/image.png" class="kg-image" alt="How we caved and created a roadmap" srcset="https://papers.draftsman.io/content/images/size/w600/2022/09/image.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/09/image.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2022/09/image.png 1600w, https://papers.draftsman.io/content/images/2022/09/image.png 1630w" sizes="(min-width: 720px) 720px"></figure><p>If you are curious, I also put a <a href="https://learning.tracepaper.draftsman.io/engine-report.html">report online</a> after converting the Tracepaper model into code. If you compare the two reports (and ignore the fact that Tracepaper has a bigger domain than the tutorial) you will notice that Tracepaper uses concepts that are not available to our clients. And there is our backlog...</p><p>The engine can do many fancy things and we even started to forget some of the features. So we decided to write down all the things that we need to model into Tracepaper, and this became some sort of a roadmap. So there you have it, the engine are enablers and we make it up as we go. But Tracepaper should make those enablers understandable to humans, and that is something we can plan.</p><!--kg-card-begin: html--><center>
    <blockquote class="trello-board-compact">
      <a href="https://trello.com/b/31IIJ3nL">Trello Board</a>
    </blockquote>
</center><!--kg-card-end: html--><p>Our velocity varies, but at least we have everything on a Trello board to keep track of the things we should do. </p>]]></content:encoded></item><item><title><![CDATA[A new feature and Why we need a KeyChain]]></title><description><![CDATA[<p>First of all, it's been a while for multiple reasons. Work, life, and the need to spend free time with friends and family. <br>The most joyous reason to not spend time alone with a computer screen is the birth of my son :)</p><p>But my son likes to sleep a lot,</p>]]></description><link>https://papers.draftsman.io/why-we-need-a-keychain/</link><guid isPermaLink="false">63022a75fd96ed0069c301d4</guid><category><![CDATA[Architecture]]></category><category><![CDATA[feature]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Thu, 22 Sep 2022 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1550527882-b71dea5f8089--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1550527882-b71dea5f8089--1-.jpg" alt="A new feature and Why we need a KeyChain"><p>First of all, it's been a while for multiple reasons. Work, life, and the need to spend free time with friends and family. <br>The most joyous reason to not spend time alone with a computer screen is the birth of my son :)</p><p>But my son likes to sleep a lot, and preferably he cuddles up inside a baby pouch close to mom or dad. So sitting here as a marsupial and listening to soothing white noise, maybe this is a good time to pick up writing again. </p><p>Efforts on Tracepaper did not stop altogether, we just entered eco-mode, nonetheless, we can announce a new feature:</p><blockquote>You can now rename the resources you previously modeled in Tracepaper!</blockquote><p>I'm fully aware this sounds lame AF, but hear me out it gets better. To understand why renaming stuff is not trivial you need insight into the segregation between read and write models that we use inside Draftsman Generated Applications.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/HLD2.1.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/HLD2.1.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/HLD2.1.png 1000w, https://papers.draftsman.io/content/images/2022/08/HLD2.1.png 1208w" sizes="(min-width: 720px) 720px"></figure><p>Let's start with the read-model (the green stuff ), the read-model is data-driven. Clients query this model for their data needs. We have to look at implementation details to understand some limitations. One of our guiding principles<a href="https://papers.draftsman.io/choosing-a/"> is serverless first</a> to minimalize cost, and operational burden while guaranteeing high performance. One of the choices that reflects this is the selection of DynamoDB.<br>DynamoDB is a high-performant key-value store with document support, it provides filtering capabilities but to guarantee performance (and low cost) you need to be smart with your keys. Limit the set to be filtered so to say.  <br>Keys in our read-model need meaning, these keys are used as identity so the client can fetch an object based on its identity.<br><strong>The first reason why our keys need meaning: clients need to know what to ask for.</strong></p><p>We use the identity as the primary key in the view-store (actually as an element of the primary key, but more on that later), you can't change your primary key (I did not work with all databases known to man, but all DB's that I worked with have this "limitation"). To tie back in with the renaming, a rename probably means changing its identity and therefore the need for updating the primary key. From the view-store perspective, this means removing the old record and inserting a new one. </p><blockquote>The view-store does not contain the truth, it is a mere projection of the truth.</blockquote><p>This means we consider the view store as volatile, meaning, we could drop this table and repopulate by replaying snapshot events. This feature has proven to be valuable during concept experimentation in our development environment.</p><p>We use a single-table design for the view store to reduce infrastructural complexity, mainly regarding system access management but also to support operations. Suppose your application receives a high load (congratulations) if that happens you could opt to switch from <a href="https://www.techtarget.com/searchcloudcomputing/answer/DynamoDB-on-demand-vs-provisioned-capacity-Which-is-better">on-demand to provisioned capacity</a> for this specific table. As stated in the <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-general-nosql-design.html">DynamoDB documentation</a>:</p><blockquote>You should maintain as few tables as possible in a DynamoDB application. Having fewer tables keeps things more scalable, requires less permissions management, and reduces overhead for your DynamoDB application. It can also help keep backup costs lower overall.</blockquote><p>How did we implement the single-table design, let's take a look at the view table in our staging environment:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/image.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/image.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/image.png 1000w, https://papers.draftsman.io/content/images/2022/08/image.png 1202w" sizes="(min-width: 720px) 720px"></figure><p>DynamoDB is a key-value store, but it does actually support the use of a 2-part composite key. This mechanism is used for the event stores and the view store, but let us focus on the latter. <br>We have a column named type, this is the partition key. A partition is a sub-collection within the view table e.g. if I would (I'll use pseudo queries for readability) <em>select document where type == 'Project' and key == 'D1562559209:personal:Demo' </em>I would receive a specific document.<br>The key field is actually a range-key, the unique identifier within this sub-collection.</p><p><em>If I fetch documents where type == 'Project'</em> I will get the whole collection. Then I could filter this set to get all Projects that belong to a certain workspace. <br>But we can do it smarter, we model our views as nodes in a graph. The entities have relations with one another. For example, a workspace contains projects and projects have subdomains, etc. If we take a look at a GraphQL query:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/image-2.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/image-2.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/image-2.png 1000w, https://papers.draftsman.io/content/images/2022/08/image-2.png 1489w" sizes="(min-width: 720px) 720px"></figure><p>We get a workspace and within this document, we expect a collection of projects. as it is a GraphQL API <a href="https://www.youtube.com/watch?v=eIQh02xuVw4">we only retrieve the information we ask for</a>. The result shown on the right side is not 1 document but the aggregation and filtering of 3 documents 1 Workspace instance and 2 Project instances. The GraphQL server "knows" it needs to perform a second query to fetch the projects (don't worry, that is one of the things we can generate). It would be wasteful to first fetch the whole Project collection to only filter it afterward. Luckily DynamoDB supports an alternative:<br><em>fetch documents where type == 'Project' and key begins with 'D1562559209:personal' </em>providing faster response times and lower cost<em>.</em><br><strong>The second reason our keys need meaning is because we use them to model hierarchy and relations.</strong></p><p>We call this a canonical-key (data architecture is not my field of expertise if you recognize this concept and know what it is called please send me a message at <a href="mailto:papers@draftsman.io">papers@draftsman.io</a>). This canonical-key plays also an important role in our access management and the way we modeled multi-tenancy, but that is a post on its own.</p><p>The way this is set up means you don't have to worry so much about cyclic dependencies in your view model. This is demonstrated in the completely nonsensical next query.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/image-3.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/image-3.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/image-3.png 1000w, https://papers.draftsman.io/content/images/2022/08/image-3.png 1493w" sizes="(min-width: 720px) 720px"></figure><p>In this query, I traverse the relation workspace &lt;-&gt; project a couple of times in a cyclic manner. Not useful in this case, but it does work nonetheless.</p><p>So a lot of reasoning has to do with modeling relational data in a non-relational database. If the data is relational why use a document based database?<br>AWS does provide a serverless relational Database <em>AWS Aurora. T</em>wo reasons why we didn't select it.<br>1. V2 was not generally available at the time we needed a decision (and V1 was not sufficient for what we wanted to do with it). <br>2. It was not serverless enough for us. It requires you to think about e.g. instance size. Secondly the pricing was not granular enough. <br>But Aurora sparks interest, so we do keep an eye on it for future updates.</p><p>Enough about querying and relations let us look at the write-model (the red stuff), the write-model is very much behavior driven. It receives events, executes some logic, and appends additional events. Determining state is the act of replaying all past events from a log.  The aforementioned event log is long-lived and therefore we can't use the canonical-key from the view model. The canonical-key has meaning and therefore it can't be inmutable. When we change the meaning of things e.g. a rename because I am human and made a typo the first time it may cause the identity to be affected as well. So no canonical-key as primary in de event stores. If we ignore this we can't change the meaning of this key without corrupting the event log.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/image-4.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/image-4.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/image-4.png 1000w, https://papers.draftsman.io/content/images/2022/08/image-4.png 1196w" sizes="(min-width: 720px) 720px"></figure><p>So the write model needs a technical key, so we chose a <a href="https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)">UUID</a>-String. And if we take a look at the event store you can see clearly see that the primary key is a UUID, this is in fact the partition key (the collection) and for the range key, we use a version number. This way the program can retrieve the whole collection and replay the events to determine the current state. Because the pair must be unique we can avoid collisions with the aid of optimistic locking.</p><p>From the client's perspective, however, I don't want t know about these keys. They are technical, better word would be internal keys. From the GraphQL API perspective I wan't to use the meaningful canonical key:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/image-5.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/image-5.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/image-5.png 1000w, https://papers.draftsman.io/content/images/2022/08/image-5.png 1156w" sizes="(min-width: 720px) 720px"></figure><p> If we would take a look at Track and Trace:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/image-6.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/image-6.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/image-6.png 1000w, https://papers.draftsman.io/content/images/2022/08/image-6.png 1165w" sizes="(min-width: 720px) 720px"></figure><p>You will see that the update was successful, and in the project event store an event is added:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/image-7.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/image-7.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/image-7.png 1000w, https://papers.draftsman.io/content/images/2022/08/image-7.png 1199w" sizes="(min-width: 720px) 720px"></figure><p>The application is perfectly capable to figure out how to translate the external key (canonical key, in our case the <em>Draftsman Resource Name</em> drn) to the internal key (UUID). To do this we introduced the key chain.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/08/image-8.png" class="kg-image" alt="A new feature and Why we need a KeyChain" srcset="https://papers.draftsman.io/content/images/size/w600/2022/08/image-8.png 600w, https://papers.draftsman.io/content/images/size/w1000/2022/08/image-8.png 1000w, https://papers.draftsman.io/content/images/2022/08/image-8.png 1205w" sizes="(min-width: 720px) 720px"></figure><p>The best part, we compressed this into the Draftsman runtime. So you only have to worry about the functional keys (You don't have to design a canonical key, but it proved to be very beneficial for us.)</p><p>Why did I ramble on for 1000+ words on key design, query concepts and whatnot if it is abstracted away? Well, I had to explain why this feature is not as lame as it sounds right? ;)</p><p>But it hasn't <em>all been champagne and caviar</em>. Not everything is magically fixed with the addition of the key-chain, some things needed modeling e.g. the cleanup of deprecated view instances. After a rename, an event is thrown that causes a new insert into the view-store instead of the usual overwrite. So we needed to model view updaters to get rid of the deprecated view instance.<br>Secondly aggregates might reference each other, e.g. a behavior-flow references a command (because it is a trigger). This reference needs to be updated, and therefore we modeled notifiers (if-this-than-that) to "fix" this. I will not go into detail, for now, I should first finish the <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">Modelling in Tracepaper series</a>.</p><p>Comments and questions are welcome at <a href="mailto:papers@draftsman.io">papers@draftsman.io</a></p><p>Cheers!<br>Bo</p>]]></content:encoded></item><item><title><![CDATA[The Beta is here!]]></title><description><![CDATA[Tracepaper is a High Productivity Framework with a designer studio. It is not done yet. But there is enough for show and tell. Start modeling in Tracepaper today!]]></description><link>https://papers.draftsman.io/we-have-a-beta-release/</link><guid isPermaLink="false">62403b7bb6a6a9006ac10986</guid><category><![CDATA[general]]></category><category><![CDATA[About Draftsman]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Tue, 05 Apr 2022 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1534670007418-fbb7f6cf32c3.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1534670007418-fbb7f6cf32c3.jpg" alt="The Beta is here!"><p>The title says it all. But before we dive in, let's recap what we wanted to build 2 years ago, what we learned, and how it changed our goals.</p><blockquote>TL;DR; Tracepaper is a High Productivity Framework with a designer studio. It is not done yet. But there is enough for show and tell. <a href="https://learning.tracepaper.draftsman.io/">Open up the tutorial and start modeling in Tracepaper!</a></blockquote><h2 id="our-guiding-design-principles"><a href="https://papers.draftsman.io/no-code-strategy/">Our guiding design principles</a></h2><ol><li>Code transparency</li><li>Serverless first approach</li><li>Visual coding concepts</li></ol><h3 id="the-pivot">The pivot</h3><p>We started building a <strong>no-code platform</strong>, but as it turns out, making everything a visual concept may cause the cognitive complexity to increase. And our goal is to decrease complexity. So fairly early on during the design of Tracepaper, we settled for a <strong>low-code platform</strong> to reach our goals.</p><p>But, low-code is kind of a misnomer, <a href="https://architectelevator.com/architecture/low-code-no-code/">Gregor Hohpe wrote a comprehensive article regarding this topic</a>. So we changed one of our guiding design principles: visual coding concepts became <em>reduce cognitive complexity! </em>We still use visualizations, but that is just a means to the goal. Are you still with me? <br>At this point, we pivoted to a <strong>High-Productivity Platform.</strong></p><p>But we are still not there, if you remember one of <a href="https://papers.draftsman.io/constraints-and-requirements/">our key constraints</a> is the fact that we are a 2 person team building this product in our spare time. So supporting a complete platform was not an option and therefore we offloaded the <a href="https://papers.draftsman.io/choosing-a/">heavy lifting to AWS</a>. So we are not a platform (PaaS) we settled for a Framework and a Designer Studio (SaaS).</p><blockquote>Draftsman engine is a <strong>High-Productivity Framework</strong> supported by a Designer Studio called Tracepaper. </blockquote><h2 id="what-did-we-build">What did we build</h2><p>Let's take a look at what we have created and how the different components fit together.</p><h3 id="the-studio">The Studio</h3><p>In Tracepaper you can <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">model your domain</a> with the aid of forms, wizards, visual models, and custom code. </p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/03/concepts.png" class="kg-image" alt="The Beta is here!"></figure><h3 id="the-engine">The engine</h3><p>The Draftsman engine converts the created model into source code. With the aid of an AWS pipeline this code gets converted into a working application.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/03/technical-concepts.png" class="kg-image" alt="The Beta is here!" srcset="https://papers.draftsman.io/content/images/size/w600/2022/03/technical-concepts.png 600w, https://papers.draftsman.io/content/images/2022/03/technical-concepts.png 607w"></figure><p>One of our guiding principles was <em>Serverless First </em>approach, therefore the entire application is constructed with AWS building blocks like:</p><!--kg-card-begin: markdown--><ul>
<li><a href="https://aws.amazon.com/lambda/">Python code in Lambda's (compute)</a></li>
<li><a href="https://aws.amazon.com/dynamodb/">Dynamodb as Database</a></li>
<li><a href="https://aws.amazon.com/cognito/">Cognito for user management</a></li>
<li><a href="https://aws.amazon.com/eventbridge/">EventBridge as a smart eventbus</a></li>
<li><a href="https://aws.amazon.com/appsync/">AppSync as a smart API (GraphQL)</a></li>
<li><a href="https://aws.amazon.com/secrets-manager/">Secrets manager... well, to manage secrets</a></li>
<li><a href="https://aws.amazon.com/cloudformation/">Cloud Formation (Infrastructure as Code) to stitch it all together</a></li>
</ul>
<!--kg-card-end: markdown--><p>The Infrastructure as Code (IaC) makes it posible to use a single repo for the entire generated application.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/03/Monolith---micro---serverless.png" class="kg-image" alt="The Beta is here!" srcset="https://papers.draftsman.io/content/images/size/w600/2022/03/Monolith---micro---serverless.png 600w, https://papers.draftsman.io/content/images/2022/03/Monolith---micro---serverless.png 813w" sizes="(min-width: 720px) 720px"></figure><p>Our aim is to reduce cost and cognitive complexity. To manage cost we use serverless, to manage the added complexity that is were te modeling comes in. The modeling tools in Tracepaper are mainly ment to handle "the grey stuff" wiring everything together. "The orange stuff" aka the business logic, the things you realy care about, those can partialy be modelled or are created by adding custom code.</p><h3 id="full-code-transparency">Full Code transparency</h3><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/03/trifecta.png" class="kg-image" alt="The Beta is here!"></figure><p>You build the app, we only generate some code. <a href="https://papers.draftsman.io/the-thought-behind-tracepaper/">That code belongs on your GitHub Repo and should be running in your AWS environment</a>. Thats how we guarantee transparency, at any moment in time you can cut us out, no problem. We aim to keep te generated code semantically clean, we improve with every itteration.</p><h2 id="we-are-not-done-yet">We are not done yet</h2><p>Okay, projects are never done, but set asside all nice to have features we could come up with. There are still a bunch of features we used to model Tracepaper but that are not yet available in Tracepaper itself. We used <a href="https://www.techopedia.com/definition/30784/dogfooding">dogfooding</a> to test the Draftsman engine. By generating Tracepaper with our own engine we found a lot of missing features (and naturally bugs). The bugs are fixed, and the features are added to the engine. Unfortunatly not all of them are in Tracepaper yet. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2022/03/estimation.png" class="kg-image" alt="The Beta is here!"><figcaption>Estimated available features in Tracepaper</figcaption></figure><p>For example, the engine can cope with: input validation, scheduled events, notifier loops, projections (running code @ query time), custom view updaters, Time To Live on data attributes (e.g. for GDPR), aggregate backups to S3, and generating GUI screens. Tracepaper, can not.</p><p> So, a lot more is to come! We will announce new features here on Papers by Draftsman. Why did we publish the beta if it is not done yet you ask? Well, the bare minimum is there, and we always promised ourselves to show it to the world once we had a working product. You have to protect yourself against overthinking and over-refining right?</p><p>Thank you for reading, <a href="https://learning.tracepaper.draftsman.io/">open up our tutorial and let's start modeling</a>. Let us know what you think, the likes and the dislikes, all feedback is valuable. <a href="https://community.draftsman.io">Use our forum for feedback and questions.</a></p><p>Cheers,<br>Bo &amp; Delano</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2022/03/george-box.png" class="kg-image" alt="The Beta is here!" srcset="https://papers.draftsman.io/content/images/size/w600/2022/03/george-box.png 600w, https://papers.draftsman.io/content/images/2022/03/george-box.png 762w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[A "minor" detour]]></title><description><![CDATA[<p>In my <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">last post</a>, I mentioned that we are designing the visual client application. And as it turns out, we both dislike building <a href="https://papers.draftsman.io/the-mirage-of-single-page-applications/">Single Page Applications</a> (SPA). Yes, "dislike" because "hate"  sounds a bit harsh. <br>Okay, I'm exaggerating a bit to get my point across. A SPA architecture is a</p>]]></description><link>https://papers.draftsman.io/a-minor-detour/</link><guid isPermaLink="false">6162f4f87bce5a0061844d69</guid><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Tue, 12 Oct 2021 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1559552006-e32abbfe5103.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1559552006-e32abbfe5103.jpg" alt="A "minor" detour"><p>In my <a href="https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/">last post</a>, I mentioned that we are designing the visual client application. And as it turns out, we both dislike building <a href="https://papers.draftsman.io/the-mirage-of-single-page-applications/">Single Page Applications</a> (SPA). Yes, "dislike" because "hate"  sounds a bit harsh. <br>Okay, I'm exaggerating a bit to get my point across. A SPA architecture is a very useful one... But only when needed, and most of the time the benefits don't <a href="https://papers.draftsman.io/focus-on-slow-growth-and-earn-your-complexity/">pay of the added complexity.</a> <br>And as it turns out, for Tracepaper building a SPA would be overkill. How did we choose a SPA in the first place? Well, we were just dazzled by the fancy GraphQL API in thinking we needed a fancy frontend framework.</p><p>How did we come to the conclusion to ditch the SPA? We were building the frontend in vuejs and even though we like this framework it just felt wrong, simply put, it was not fun building the frontend. And in my honest opinion, building software should always be fun, if it is not fun there is something wrong. And most of the time it has to do with Technical Debt. </p><p>Technical Debt has the tendency to suck all the fun right out of your development project. In this case, we had encountered some Architectural Debt. We chose a front-end architecture that didn't fit with our vision. Like hammering a square peg into a round hole, you are going to have a bad time.</p><p>What to do... We are getting fairly good in code generation, so let's do that. In the past 3 weeks, we expanded our generator and the <em>draftsman modeling language </em>to support what we call "screens &amp; widgets".  What kind of models you ask, we'll get there eventually with the <a href="https://papers.draftsman.io/tag/modeling-in-tracepaper/">Modeling in Tracepaper</a> series.</p><p>On a closing note, you assumed correctly that we don't generate a SPA. Inspired by a post from Aaron Swartz called <a href="http://www.aaronsw.com/weblog/000404">"Bake, don't fry"</a> and the principles behind the <a href="https://jamstack.org/what-is-jamstack/">JAMstack methodology</a> we prerender as much as we can and host it from a CDN. It is simple and fast, and that brings the fun back into our front-end design.</p>]]></content:encoded></item><item><title><![CDATA[Modeling in Tracepaper: Concept overview]]></title><description><![CDATA[<p>At the moment we are designing the visual client application, and now questions arise, how do concepts fit together? Not in a technical sense, but in a conceptual. At Draftsman we use two different models to describe applications, let's sum them up so we are on the same page.</p><ul><li>Conceptual</li></ul>]]></description><link>https://papers.draftsman.io/modeling-in-tracepaper-part-1-concept-overview/</link><guid isPermaLink="false">613888d0a48fde006191e64b</guid><category><![CDATA[Modeling in Tracepaper]]></category><category><![CDATA[About Draftsman]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Tue, 21 Sep 2021 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1513364776144-60967b0f800f.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1513364776144-60967b0f800f.jpg" alt="Modeling in Tracepaper: Concept overview"><p>At the moment we are designing the visual client application, and now questions arise, how do concepts fit together? Not in a technical sense, but in a conceptual. At Draftsman we use two different models to describe applications, let's sum them up so we are on the same page.</p><ul><li>Conceptual model: This model describes the application and its behavior in ubiquitous therms. This means you will encounter concepts like Command, Behavior, Domain Event, and View. The stuff you could map out with sticky notes during an event storming workshop. This is the kind of modeling we should enable with aid of the Tracepaper GraphQL API and subsequently our user interface.</li><li>Transfer model: an XML representation of the above model with a slight difference, the optimization goal for the conceptual model is to be human-readable or at least human-reasonable. While the Transfer Model is optimized to be machine-readable.</li></ul><p>Our transfer model is XML based which we dubbed "Draftsman Modelling Language" it is nearly complete in the context of the MVP due to the fact we use this language to model the Tracepaper backend itself. And to be honest, this way you find the most urgent missing features in a timely manner. Features we probably wouldn't have envisioned if we tried to design it upfront. <br>Now for the API, we modeled a lot but we are not there yet... we have to figure out what data views we need, the best way to figure out what you need is to explain what you want to achieve. So here we go.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/09/concepts.png" class="kg-image" alt="Modeling in Tracepaper: Concept overview"></figure><p>As stated in the introduction we want to optimize our modeling tool to fit with event storming and customer journeys and therefore we condensed our problem space to 5 core concepts.</p><p>A <strong>command </strong>is the starting point of a... let's call it a call stack to keep it simple. A command is considered a fat trigger composed of input fields. The command will trigger <strong>behavior</strong> in the domain, in this context behavior is the application of business rules on stateful data. The behavior may result in a domain event or also called a <strong>change event, </strong>the change events are persistent and used to reconstruct the state. You can see that we composed behavior and change-event right next to each other in this image, this is not a coincidence these concepts are strongly coupled, you could have multiple behavior-flows acting on a single event-log that is our implementation of an <a href="https://martinfowler.com/bliki/DDD_Aggregate.html">aggregate</a>. But that is a topic for another post, because, the event is not only persisted it is also published within our domain. And then interesting things can happen, other components could react to the event "if this then that". We have a concept called <strong>notifier </strong>designed to do exactly that, notify another system, maybe you want to trigger an email using the AWS Simple Email Service, or store a document in AWS Simple Storage Service. A notifier is simply said, an event-to-command converter it invokes APIs from AWS, third party, your on-premise application, or even its own.<br>Another thing that could happen after an event, is triggering a state change in a <strong>view. </strong>You may have noticed the use of <a href="https://martinfowler.com/eaaDev/EventSourcing.html">event sourcing</a> for our persistence strategy, very powerful for storing aggregates, horrible for querying. Therefore we use another pattern called <a href="https://martinfowler.com/bliki/CQRS.html">Command Query Responsibility Segragation</a> to mitigate this hurdle. We literally use a different model for our query model, there are other reasons why we use this strict segregation, but this topic deserves a dedicated post.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/09/concepts_api.png" class="kg-image" alt="Modeling in Tracepaper: Concept overview" srcset="https://papers.draftsman.io/content/images/size/w600/2021/09/concepts_api.png 600w, https://papers.draftsman.io/content/images/2021/09/concepts_api.png 861w" sizes="(min-width: 720px) 720px"></figure><p>Knowing the core concepts it is not difficult to see how a <a href="https://papers.draftsman.io/designing-an-api/">GraphQL API</a> correlates to our model. Thanks for reading.</p><p>Here is a sneak preview, our <a href="https://papers.draftsman.io/over-the-hill/">generator</a> will convert your model into something like this:</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/09/technical-concepts.png" class="kg-image" alt="Modeling in Tracepaper: Concept overview" srcset="https://papers.draftsman.io/content/images/size/w600/2021/09/technical-concepts.png 600w, https://papers.draftsman.io/content/images/2021/09/technical-concepts.png 607w"></figure>]]></content:encoded></item><item><title><![CDATA[Back to school]]></title><description><![CDATA[<p>Holidays are over and kids are going back to school, now is a good time to share what we've been up to last month. We did take a break from writing posts to focus on implementing ideas, and that we did.</p><p>We came a long way and I'm proud to</p>]]></description><link>https://papers.draftsman.io/back-to-school/</link><guid isPermaLink="false">61300f617461610061bce4a1</guid><category><![CDATA[general]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Tue, 07 Sep 2021 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1535982330050-f1c2fb79ff78.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1535982330050-f1c2fb79ff78.jpg" alt="Back to school"><p>Holidays are over and kids are going back to school, now is a good time to share what we've been up to last month. We did take a break from writing posts to focus on implementing ideas, and that we did.</p><p>We came a long way and I'm proud to announce that last week we performed a successful integration test on the Tracepaper API. In a <a href="https://papers.draftsman.io/the-thought-behind-tracepaper/">previous post</a>, we presented a component view of what we intended to build. With the MVP in mind, rough estimate, 85% of our API is implemented. The other 15% is fine-tuning, the stuff we postponed during our <a href="https://papers.draftsman.io/tracepaper-our-first-design-session/">event storming sessions</a>, you can't focus on everything right?</p><p>The biggest challenge for September is implementing a comprehensive front-end that aligns with the customer journeys we envisioned while harnessing the power of our API. Why did we postpone the front end you ask? Well, from a value perspective it is the make-or-break component of our product. To do it well is the biggest challenge we will face, this challenge however is from a UX design perspective. It is a big mental investment and we were not ready to put in the effort before we proved our idea is feasible.  </p><p>Therefore, we build a test tool, a fairly simple script that invokes the different API functions to model a simple "Single Command, Single View" application. I bet you can imagine our euphoria when after a mere evening of bug fixing running our test script resulted in a deployed and functional generated serverless application.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/09/backend-update-1.png" class="kg-image" alt="Back to school" srcset="https://papers.draftsman.io/content/images/size/w600/2021/09/backend-update-1.png 600w, https://papers.draftsman.io/content/images/size/w1000/2021/09/backend-update-1.png 1000w, https://papers.draftsman.io/content/images/2021/09/backend-update-1.png 1041w" sizes="(min-width: 720px) 720px"></figure><p>So what's next? Dotting the I's and crossing the T's as they say, in our case this will be: Implementing front-end features &gt; Refining Backend &gt; Refining Generator  &gt; Repeat.</p><p>And for the next post? I think it is time to write a series about the concepts we use in our Draftsman Modeling Language, stay tuned.</p>]]></content:encoded></item><item><title><![CDATA[Have a great summer!]]></title><description><![CDATA[<p>School's out for summer, a great time to step back, relax, and recharge. Leisure time with friends and family and hopefully some sunny weather. So for the next couple of weeks, it will be quiet on Papers by Draftsman.</p><p>Draftsman is still a hobby project, which means work is not</p>]]></description><link>https://papers.draftsman.io/have-a-great-summer/</link><guid isPermaLink="false">60eeea16cbe1f0007f8850d2</guid><category><![CDATA[general]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Tue, 20 Jul 2021 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1473496169904-658ba7c44d8a.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1473496169904-658ba7c44d8a.jpg" alt="Have a great summer!"><p>School's out for summer, a great time to step back, relax, and recharge. Leisure time with friends and family and hopefully some sunny weather. So for the next couple of weeks, it will be quiet on Papers by Draftsman.</p><p>Draftsman is still a hobby project, which means work is not paused altogether. Work on Tracepaper will continue as is, which is when we feel like it 😉</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/07/strategy-2.png" class="kg-image" alt="Have a great summer!" srcset="https://papers.draftsman.io/content/images/size/w600/2021/07/strategy-2.png 600w, https://papers.draftsman.io/content/images/2021/07/strategy-2.png 981w" sizes="(min-width: 720px) 720px"></figure><p>We did arrive at an exciting milestone in the development of Tracepaper, version 4 of our generator is operational and deployed to the cloud. This means we now can incorporate the whole product in our iterative process instead of two detached islands of technology. Delano and I collaborated during two event-storming workshops in June where we had discussions regarding our domain, customer journeys, and the relevant events around those journeys. Service Design was a key aspect of those sessions and we mapped part of our domain with paper and tape. Which part? Well, the minimal set of functional concepts we need to get the MVP up and running. At the moment we are converting the <em>paper and tape model</em> into <em>Draftsman Modeling Language</em> (XML). A rough estimate, I think we have 65% for the Tracepaper back-end done right now and we are excited to start integrating the visual layer. <br><br>You will hear from us in September. For now, have a great summer and stay healthy!<br><br>Cheers,<br>Delano &amp; Bo</p><p></p>]]></content:encoded></item><item><title><![CDATA[Draw The Line]]></title><description><![CDATA[<h3 id="bubbles-of-complexity">Bubbles of complexity</h3><p>We use serverless techniques to handle unpredictable loads while keeping operational costs to a minimum. Nothing in life is free, and we do pay in <a href="https://papers.draftsman.io/beware-of-the-merchants-of-complexity/">complexity</a>.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/07/Monolith---micro---serverless-1.png" class="kg-image" alt srcset="https://papers.draftsman.io/content/images/size/w600/2021/07/Monolith---micro---serverless-1.png 600w, https://papers.draftsman.io/content/images/2021/07/Monolith---micro---serverless-1.png 813w" sizes="(min-width: 720px) 720px"></figure><p>We tackle this complexity by making sure that the technology supports the design and not the other way around, my <a href="https://papers.draftsman.io/the-thought-behind-tracepaper/">previous</a></p>]]></description><link>https://papers.draftsman.io/draw-the-line/</link><guid isPermaLink="false">60e36b79e2de66007f801ade</guid><category><![CDATA[Technology Stack]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Tue, 13 Jul 2021 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1523552832376-ffee9bbda123.jpg" medium="image"/><content:encoded><![CDATA[<h3 id="bubbles-of-complexity">Bubbles of complexity</h3><img src="https://papers.draftsman.io/content/images/2022/09/photo-1523552832376-ffee9bbda123.jpg" alt="Draw The Line"><p>We use serverless techniques to handle unpredictable loads while keeping operational costs to a minimum. Nothing in life is free, and we do pay in <a href="https://papers.draftsman.io/beware-of-the-merchants-of-complexity/">complexity</a>.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/07/Monolith---micro---serverless-1.png" class="kg-image" alt="Draw The Line" srcset="https://papers.draftsman.io/content/images/size/w600/2021/07/Monolith---micro---serverless-1.png 600w, https://papers.draftsman.io/content/images/2021/07/Monolith---micro---serverless-1.png 813w" sizes="(min-width: 720px) 720px"></figure><p>We tackle this complexity by making sure that the technology supports the design and not the other way around, my <a href="https://papers.draftsman.io/the-thought-behind-tracepaper/">previous post</a> mentioned we use majestic monolithic thinking to design our applications and merge this with serverless concepts by using an event-driven architecture. Our latest version of the <a href="https://papers.draftsman.io/over-the-hill/">generator</a> uses a monolithic model as input, generates code, packages this code as microservices, and deploys it as function as a service. This approach compresses the conceptual complexity away from our business domain, but there is another disadvantage in event-based systems that needs solving.</p><p>Event-based means goodbye call stack! The <a href="https://2007.debs.org/hohpe.pdf">architect's dream regarding loose coupling may as well be the developer's nightmare</a> to debug. It introduces a lot of uncertainty regarding failure. Can we pinpoint the component that failed? Where are the logs? How do we set up proactive monitoring, and then what? Amazon Web Services (AWS) does provide a managed service to set up monitoring, it is called X-ray. But that is where we drew the line so to speak.</p><p>The thing we try to do is quite ambitious, venturing out into another realm of complexity does not sound like a good idea. Truth be told, analytics and monitoring is not our core competence. We decided we didn't want to pay the <a href="https://aws.amazon.com/blogs/enterprise-strategy/revisiting-buy-vs-build-3-traps-to-avoid/">opportunity cost</a> to learn how to do it ourselves... We "buy" it.</p><h3 id="finding-a-vendor-that-sells-observability">Finding a vendor that sells Observability</h3><p>Everyone is giving out free samples, and that is how our quest began. The first platform we tried was <a href="https://www.bluematador.com/">bluematador.com</a>, a good solution but not the right fit for us. Not a good fit for the same reason that <a href="https://www.datadoghq.com/">Data Dog</a> didn't feel right, the "problem" with these first two solutions is that you could measure practically anything you want, especially with Data Dog. Very impressive stuff, the thing is, more bells and whistles mean you have a steeper learning curve. This is fine if you're into big data analyses. But adding an extra bubble of complexity is something we want to avoid, we are looking for intuitive distributed tracing with minimal setup. Intuitive is a broad spectrum, so let me clarify. We are looking for a product that delivers distributed tracing for serverless applications on AWS that has minimal setup and is intuitive to use for two developers with a Java background in a Service-Oriented environment. So, we are looking for something more opinionated, and that is when we landed on <a href="https://dashbird.io/">Dashbird.io</a> and <a href="https://lumigo.io/">Lumigo.io</a>.</p><p>Both products are easy to set up and use, but we felt that Lumigo was more opinionated in <a href="https://lumigo.io/blog/">how you should build a serverless application</a> on AWS, which drew us over.</p><p>We are happy with our choice and found some nasty bugs in our code with the provided tooling, and even re-architected our GraphQL API. Are we ever going to use AWS's X-Ray? Well, I don't know, but for the foreseeable future, Lumigo is our monitor.</p><p>As I sign off for this weeks blogpost, I will leave you with some screenshots from Lumigo so you can see why we are so enthusiastic about this tool. Until next time.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2021/07/image-1.png" class="kg-image" alt="Draw The Line" srcset="https://papers.draftsman.io/content/images/size/w600/2021/07/image-1.png 600w, https://papers.draftsman.io/content/images/size/w1000/2021/07/image-1.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2021/07/image-1.png 1600w, https://papers.draftsman.io/content/images/2021/07/image-1.png 1904w" sizes="(min-width: 720px) 720px"><figcaption>A single business transaction with all invoked components and logging.</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2021/07/image-2.png" class="kg-image" alt="Draw The Line" srcset="https://papers.draftsman.io/content/images/size/w600/2021/07/image-2.png 600w, https://papers.draftsman.io/content/images/size/w1000/2021/07/image-2.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2021/07/image-2.png 1600w, https://papers.draftsman.io/content/images/2021/07/image-2.png 1809w" sizes="(min-width: 720px) 720px"><figcaption>And the timeline view from that same call stack</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://papers.draftsman.io/content/images/2021/07/image-3.png" class="kg-image" alt="Draw The Line" srcset="https://papers.draftsman.io/content/images/size/w600/2021/07/image-3.png 600w, https://papers.draftsman.io/content/images/size/w1000/2021/07/image-3.png 1000w, https://papers.draftsman.io/content/images/size/w1600/2021/07/image-3.png 1600w, https://papers.draftsman.io/content/images/2021/07/image-3.png 1920w" sizes="(min-width: 720px) 720px"><figcaption>With the issue dashboard we can find faulty code without hand-checking all logs</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/07/image-4.png" class="kg-image" alt="Draw The Line" srcset="https://papers.draftsman.io/content/images/size/w600/2021/07/image-4.png 600w, https://papers.draftsman.io/content/images/2021/07/image-4.png 901w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[We don't know if you read our posts and why we're totally fine with it]]></title><description><![CDATA[<p>Many companies, and even individuals, send us many emails. Some of them because we are a customer and others because we have subscribed to their newsletter. Either way, most of these companies are trying to contact us with new information, or even exclusive newsletter deals, convert us to buy their</p>]]></description><link>https://papers.draftsman.io/we-dont-know-if-you-read-our-posts-and-why-were-totally-fine-with-it/</link><guid isPermaLink="false">60e351d2e2de66007f801a46</guid><category><![CDATA[About Draftsman]]></category><dc:creator><![CDATA[Delano Cörvers]]></dc:creator><pubDate>Tue, 06 Jul 2021 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2021/07/etienne-girardet-CxTCcjUo2hM-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2021/07/etienne-girardet-CxTCcjUo2hM-unsplash.jpg" alt="We don't know if you read our posts and why we're totally fine with it"><p>Many companies, and even individuals, send us many emails. Some of them because we are a customer and others because we have subscribed to their newsletter. Either way, most of these companies are trying to contact us with new information, or even exclusive newsletter deals, convert us to buy their products or services time and time again. We might even be genuinely interested in what these companies or individuals have to say. But with that comes unwanted invasion of privacy through <a href="https://en.wikipedia.org/wiki/Email_tracking">tracking</a> their readers.</p><p>There aren't many companies out there who don't (ab)use the usage of e-mail tracking. Potentially every e-mail you receive, that's not directly from an individual you know, has a high chance of containing some form of e-mail tracking. The tracking of e-mails can go so far that these companies not only know you have opened an e-mail. But also how long you've had it open, what links you clicked or how you generally interact with their e-mails. Their smart tracking systems can tell them about what smartphone or laptop you have, at what time you read their e-mail and even how often you check back on that e-mail they sent you. Haven't read their latest additions to your inbox? Don't worry, they won't mind reminding you every once in a while that you haven't opened their most recent e-mails if you have decided to take a little break.</p><p><a href="https://en.wikipedia.org/wiki/Spy_pixel">Spy Pixels</a> are slowly invading our e-mail box. And with that, these companies are invading our privacy. Most of us don't even realize these spy pixels exist or the amount of information they reveal about you. This has to stop.</p><p>Ever since <a href="https://www.hey.com/">Hey.com</a> has been released in 2020, with <a href="https://www.hey.com/spy-trackers/">blocking e-mail Spy Pixels</a> as one of its main features, more and more companies are deciding to let go of their e-mail tracking. Even Apple has recently announced that they will be blocking e-mail tracking with the default Mail app starting with their next software release in the fall. This is a huge development when it comes to privacy as now Spy Pixels and e-mail tracking will finally have a chance to become obsolete.</p><p>At Draftsman.io we are very passionate about doing right by our readers and, in the future, our users. We value transparency in what we do and what we do with your information. From the start one of our drivers was to generate beautiful serverless applications based on your models, where the generated code is readable and fully transparent. You own the code we generated, wether you decide to stay with us or leave us. When we started our blog Papers by Draftsman.io, we wanted to have the same transperancy. And since this e-mail tracking endemic recently surfaced again in a much larger way than ever before, we decided that we would never include any tracking in our e-mails starting from day one.</p><p>Obviously we are still looking to grow our audience, and we would love to welcome you onto our newsletter. For us, this means that we use a specific tool to give us anonymous insight into how our blog is doing. <a href="https://analytics.bohanssen.com/papers.draftsman.io">Plausible.io</a> gives us insight in the amount of unique visitors we have had and how often certain pages have been looked up. We also see how this visitor found their way to our blog, maybe through our newsletter, a search engine or a direct link. All we see is anonymous information. We don't see any information about our individuals viewers, and we have no idea who you are. The web is entirely free, as it should be. And for us, well we can't think of anything better than letting our readers decide if and when they wanna read. We don't need to be in the loop via tracking.</p><p>So, we don't know if you have read our posts. And we're totally fine with it. Of course, we would love to hear from you! If you have any questions or feedback, don't hesitate to shoot us a message at <a href="mailto:papers@draftsman.io">papers@draftsman.io</a>.</p>]]></content:encoded></item><item><title><![CDATA[Draftsman: What's in a name?]]></title><description><![CDATA[<p>For this particular post, I would like to take you back about one year and three months. It was the beginning of Spring 2020, right before the pandemic hit, and Bo started sharing his new idea and vision for complex transactional serverless applications. We went back and forth for a</p>]]></description><link>https://papers.draftsman.io/draftsman-whats-in-a-name/</link><guid isPermaLink="false">60da12884bbe8a007f483308</guid><category><![CDATA[general]]></category><category><![CDATA[About Draftsman]]></category><dc:creator><![CDATA[Delano Cörvers]]></dc:creator><pubDate>Tue, 29 Jun 2021 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2021/06/ryan-ancill-nGsVMkRatgM-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2021/06/ryan-ancill-nGsVMkRatgM-unsplash.jpg" alt="Draftsman: What's in a name?"><p>For this particular post, I would like to take you back about one year and three months. It was the beginning of Spring 2020, right before the pandemic hit, and Bo started sharing his new idea and vision for complex transactional serverless applications. We went back and forth for a few weeks discussing his ideas. Some elements that always came back were modeling our software (Model Driven Design) so that a business analyst could create a complex application, by just clicking together what they needed. Naturally, we focused on <a href="https://en.wikipedia.org/wiki/Domain-driven_design">Domain Driven Design</a> (DDD) since it allows us to focus on the context of the business and in the language the business analysts, domain experts and developers already know.</p><p>During these sessions we started to notice that the work we do as software engineers and architects, especially when basing our work on Model Driven Development, had a lot of similarities with the work of an <a href="https://en.wikipedia.org/wiki/Architect">Architect</a>. When we look at the construction of a building, the architect is responsible for creating a solid foundation to build upon and structural integrity, as well as designing the building in such a way that it appeals to its audience. The architect hands his designs off to a contractor who will then begin the building process. In software engineering, specifically at Draftsman, we are trying to do the same. We draw up the designs and architecture of a system, using tools such as DDD, and based on these drawings we generate a fully functioning serverless application. The business analysts, also known as domain experts, design the system (draw) and the Draftsman Engine will turn those designs into high quality functional code.</p><p>This analogy with Architects became a theme, so much so that we decided to look in this realm for a good name for our project. Through many searches in <a href="https://onelook.com/">OneLook</a> related to architects and the tools they use we landed on some promising names. One of these was Draftsman. A draftsman is, according to the definition on <a href="https://www.macmillandictionary.com/dictionary/american/draftsman#draftsman_6">MacMillen</a>, someone whose job it is to draw the plans for something that someone is going to make or build. In other sources a draftsman is considered a master builder, a craftsman or even an architect. We just knew that when we landed on this name that this was the one. I'm sure you can imagine the excitement we felt when <a href="https://draftsman.io/">Draftsman.io</a> was still available.</p><p>We got the name of our project covered and we're very happy with it. But we also have a designer studio that we wanted to build. Like I mentioned earlier, we also searched for tools in an architects toolkit. We came across many different tools, such as a lead holder and tracepaper. Tracepaper is the paper that is used by architects, or draftsmans, to draw their technical designs on. And, if you're catching our drift, it seemed like the perfect fit to us. Without hesitation it just clicked and from that moment on our designer studio was labeled Tracepaper.</p><p>What made these two names stand-out to us? Well for one, in Search Engine Optimization it is recommended that your brand name is a unique one-word word. Which narrowed down our options significantly. And from there, we just fell in love with the relation to Architects. On top of that, these are great brand names to carry the message we want to share with the world. Even <a href="https://papers.draftsman.io/">Papers by Draftsman</a> is a carefully chosen name that fits inside this little ecosystem we created so far.</p><p>I hope you enjoyed this different take on our posts this week. For now we are going to continue working on our dream to build the most accessible designer studio that is capable of designing world-class transactional software, in the cloud. Until next time.</p>]]></content:encoded></item><item><title><![CDATA[The thought behind Tracepaper]]></title><description><![CDATA[<p>In a previous post, I mentioned we are <a href="https://papers.draftsman.io/over-the-hill/">over the hill</a>, the complex technical preparations are completed. We <a href="https://papers.draftsman.io/tracepaper-our-first-design-session/">started designing</a> our application. Designing what exactly? We <a href="https://papers.draftsman.io/why-we-dont-have-a-roadmap/">don't have a roadmap</a> after all.</p><p>Our mission is, enabling business-minded people to model performant cloud-native applications while reducing operational burden. We selected Model-Driven</p>]]></description><link>https://papers.draftsman.io/the-thought-behind-tracepaper/</link><guid isPermaLink="false">60c652ac14f07e007f7b934c</guid><category><![CDATA[About Draftsman]]></category><category><![CDATA[Architecture]]></category><category><![CDATA[Design]]></category><category><![CDATA[Strategy]]></category><dc:creator><![CDATA[Bo Hanssen]]></dc:creator><pubDate>Tue, 22 Jun 2021 09:00:00 GMT</pubDate><media:content url="https://papers.draftsman.io/content/images/2022/09/photo-1594377157609-5c996118ac7f.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://papers.draftsman.io/content/images/2022/09/photo-1594377157609-5c996118ac7f.jpg" alt="The thought behind Tracepaper"><p>In a previous post, I mentioned we are <a href="https://papers.draftsman.io/over-the-hill/">over the hill</a>, the complex technical preparations are completed. We <a href="https://papers.draftsman.io/tracepaper-our-first-design-session/">started designing</a> our application. Designing what exactly? We <a href="https://papers.draftsman.io/why-we-dont-have-a-roadmap/">don't have a roadmap</a> after all.</p><p>Our mission is, enabling business-minded people to model performant cloud-native applications while reducing operational burden. We selected Model-Driven Development to separate design from implementation details.</p><p>In Tracepaper (our design studio) we promote <a href="https://papers.draftsman.io/why-a-monolith-might-be-better-than-a-microservice-architectures/">monolithic</a> thinking because from a business perspective the system has to be viewed as a whole otherwise it would lose its fundamental properties.</p><blockquote>A system is a whole that cannot be divided into independent parts. The defining properties of any system are properties of the whole, which none of its parts have.<br> <br>The essential property of an automobile is that it can carry you from one place to another. No part of an automobile can do that. <br>The wheel can’t, the axle can’t, the seat can’t, the motor can’t. <br>The motor can’t even carry itself from one place to another. <br><br>You can write; your hand can’t write. That’s easy to demonstrate: cut it off, put it on a table, and watch what it does… nothing! <br><br>And, therefore: when a system is taken apart, it loses its essential properties. - <a href="https://youtu.be/OqEeIG8aPPk?t=233">Russ Ackoff</a></blockquote><p>For the performant cloud-native application part we chose to use serverless concepts and selected AWS as a vendor to do so. This means that for now at least Tracepaper will only support AWS... sorry folks.</p><p>Stitching together monolithic design and serverless implementation means we have to look for a common denominator between those two perspectives. The answer is events. This means we have to treat events as first-class citizens and subsequently use event-driven architecture. I can not tell you how we visually support this in Tracepaper because this is one of the things we are designing at this moment. But we will address this in-depth once we have succeeded.</p><p>The important part is, from the business perspective we have a model. And with the aid of a <a href="https://papers.draftsman.io/no-code-strategy/">generator</a>, we convert this model into deployable code.</p><p>One of our core values is transparency. You may choose to use Tracepaper for your next back-end application, and although we generate code for you, it is your code. We built a modeling studio and a generator, that is ours. But the code that this generator spits out reflects your thoughts. And your thoughts are certainly not our property.</p><p>Furthermoe, running your own code in a managed serverless platform is an agreement between you and the cloud provider. You should be reticent to whom you give insight into your applications at runtime. A need to know basis as you will, and we at Draftsman just don't need to know, and thus we won't.</p><p>We do trust another company to help us monitor our serverless applications, but I will discuss why we selected <a href="https://lumigo.io/">lumigo.io</a> in another post.</p><p>To sum up, we create an application to manage models that reflect your business domain, this is our design studio Tracepaper. We need a component that converts said models into code. And we want to give our clients full ownership over code and operations.</p><h2 id="component-view-and-ownership-perspective">Component view and ownership perspective</h2><p>In the high-level design depicted below, you can see a clear distinction between our cloud environment and the client cloud environment. The commit from the generator to GitHub is the handover in ownership.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/06/HLD-cloud-indeling.png" class="kg-image" alt="The thought behind Tracepaper" srcset="https://papers.draftsman.io/content/images/size/w600/2021/06/HLD-cloud-indeling.png 600w, https://papers.draftsman.io/content/images/size/w1000/2021/06/HLD-cloud-indeling.png 1000w, https://papers.draftsman.io/content/images/2021/06/HLD-cloud-indeling.png 1061w" sizes="(min-width: 720px) 720px"></figure><p>This does mean, that you will need an AWS and GitHub account besides your Draftsman account. We are aware this may be an extra hurdle for using our platform but we accepted this drawback. Why? because it supports an excellent exit strategy. If at any point in time you decide you don't like Draftsman anymore, you can cut us out, no problem. The code is yours, in a repository that you own and running on machinery that you rent. We strive to make the generated code readable and as maintainable as possible, what you do with it after that, that's up to you.</p><figure class="kg-card kg-image-card"><img src="https://papers.draftsman.io/content/images/2021/06/trifecta.png" class="kg-image" alt="The thought behind Tracepaper"></figure><h2 id="what-we-are-working-on">What we are working on</h2><p>At the moment we are designing the back-end for Tracepaper, we do this in the XML-based modeling language we invented as input for our generator. A very useful process, we already added some missing features in language and generator. We aim to conclude this stage by the end of this month. The next step is for Delano to integrate the Tracepaper front-end using the <a href="https://papers.draftsman.io/designing-reference-cards-and-the-power-of-utility-first-css/">prepared building blocks</a>. Meanwhile, I will focus on integrating the <a href="https://papers.draftsman.io/over-the-hill/">last iteration</a> of our generator into the Draftsman Serverless landscape and start working on automation to aid the client in attaching Draftsman, GitHub and AWS together. </p>]]></content:encoded></item></channel></rss>