<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>JBake</title>
    <link>https://fiveandahalfstars.ninja</link>
    <atom:link href="https://fiveandahalfstars.ninja/feed.xml" rel="self" type="application/rss+xml" />
    <description>JBake Bootstrap Template</description>
    <language>en-gb</language>
    <pubDate>Thu, 9 Apr 2026 17:49:56 +0000</pubDate>
    <lastBuildDate>Thu, 9 Apr 2026 17:49:56 +0000</lastBuildDate>

    
    <item>
      <title>Gelesen: Sketchnotes in der IT von Lisa Maria Moritz</title>
      <link>https://fiveandahalfstars.ninja/blog/2021/2021-08-01-Sketchnotes.html</link>
      <pubDate>Thu, 9 Apr 2026 17:49:23 +0000</pubDate>
      <guid isPermaLink="false">blog/2021/2021-08-01-Sketchnotes.html</guid>
      <description>
      &lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Gerade richtig zum Wochenende landete das Buch &lt;a href=&quot;https://amzn.to/3CjN2on&quot;&gt;Sketchnotes in der IT&lt;/a&gt; in meinem Briefkasten.
Ich bewundere schon länger die Sketchnotes von Lisa und hoffe immer wieder, dass sie in einem meiner Vorträge sitzt und ich im Anschluss einen Tweet mit der graphischen Zusammenfassung auf ihrem Twitter-Kanal &lt;a href=&quot;https://twitter.com/Teapot4181/status/1339614445031579650&quot;&gt;@Teapot4181&lt;/a&gt; bewundern kann.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Jetzt ist ihr Buch draußen und ich habe das schöne Wetter am Wochenende genutzt, um es zu verschlingen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;a class=&quot;image&quot; href=&quot;https://amzn.to/3CjN2on&quot;&gt;&lt;img src=&quot;../../images/blog/2021/Sketchnotes-Buch.png&quot; alt=&quot;Sketchnotes Buch&quot;&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das Buch gliedert sich hauptsächlich in zwei Teile.
Im ersten Teil erklärt Lisa die Grundlagen ihrer Sketchnotes und auch ihre Tipps und Tricks um erfolgreich starten zu können.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im zweiten Teil öffnet Lisa für uns ihre kreative Bibliothek an Symbolen, die sie für ihre IT-Sketchnotes benutzt.
Darunter befinden sich viele clevere Icons (ich liebe die Symbole für Backend und Frontend!), die mir bei meinen ersten Gehversuchen auch gleich gut weiter geholfen haben.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Am Spannendsten fand ich aber die Argumentation, dass Sketchnotes die Konzentration fördern und die visuellen Notizen sich viel besser nachschlagen lassen.
Dem kann ich nach der Lektüre nur zustimmen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Allen, die ihren Lernhunger visuell unterstützen wollen, kann ich &lt;a href=&quot;https://amzn.to/3CjN2on&quot;&gt;das Buch&lt;/a&gt; empfehlen!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2021/microsites-sketchnote.png&quot; alt=&quot;microsites sketchnote&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
auf dieser Seite verwende ich affiliate Links um meine Website damit zu finanzieren.&lt;br&gt;
Danke für Dein Verständnis ♥.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Peter Naur, Stochastic Parrots, and the Future of Software Architecture: My Thoughts from Software Architecture Gathering 2024</title>
      <link>https://fiveandahalfstars.ninja/blog/2025/2025-12-05-iSQB-Software-Architecture-Gathering.html</link>
      <pubDate>Fri, 5 Dec 2025 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2025/2025-12-05-iSQB-Software-Architecture-Gathering.html</guid>
      <description>
      &lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot;&gt;Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_a_conference_between_tradition_and_transformation&quot;&gt;A Conference Between Tradition and Transformation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_the_forgotten_foundation_peter_naurs_mental_model&quot;&gt;The Forgotten Foundation: Peter Naur&amp;#8217;s Mental Model&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_semantic_anchors_the_bridge_between_humans_and_machines&quot;&gt;Semantic Anchors: The Bridge Between Humans and Machines&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_todo_replace_human_coding_with_ai&quot;&gt;#TODO: Replace Human Coding With AI?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_the_stochastic_parrot_understanding_limitations&quot;&gt;The Stochastic Parrot: Understanding Limitations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_the_fish_bowl_human_intelligence_vs_artificial_intelligence&quot;&gt;The Fish Bowl: Human Intelligence vs. Artificial Intelligence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_arc42_in_education_a_conversation_with_claudine_allen&quot;&gt;arc42 in Education: A Conversation with Claudine Allen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_my_core_theses&quot;&gt;My Core Theses&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_1_the_mental_model_remains_central&quot;&gt;1. The Mental Model Remains Central&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_2_semantic_anchors_as_key_technology&quot;&gt;2. Semantic Anchors as Key Technology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_3_understand_dont_just_generate&quot;&gt;3. Understand, Don&amp;#8217;t Just Generate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_4_education_must_adapt&quot;&gt;4. Education Must Adapt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_the_future_of_software_architecture&quot;&gt;The Future of Software Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Last week, I had the honor of speaking before an international audience at the iSAQB&amp;#8217;s Software Architecture Gathering in Berlin. The conference offered not only technical depth but also philosophical perspectives on the future of our discipline in the age of GenAI.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_a_conference_between_tradition_and_transformation&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_a_conference_between_tradition_and_transformation&quot;&gt;&lt;/a&gt;A Conference Between Tradition and Transformation&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Peter Hruschka opened the conference with his keynote – without any mention of GenAI. A deliberate contrast to what would follow. Stefan Toth laid the foundation with his talk for my own presentation about the future of software architecture and development with GenAI.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_the_forgotten_foundation_peter_naurs_mental_model&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_the_forgotten_foundation_peter_naurs_mental_model&quot;&gt;&lt;/a&gt;The Forgotten Foundation: Peter Naur&amp;#8217;s Mental Model&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When I asked who was familiar with the name Peter Naur, only about 3 hands went up in the room. One of them was Avraham Poupko – more on that in a moment. This was a surprising moment because Naur&amp;#8217;s concept of the &quot;mental model&quot; from his essay &quot;Programming as Theory Building&quot; (1985) is more fundamental than ever.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Naur argued that a program is not its source code, but rather a shared mental construct that lives in the minds of the people who work on it. The code is merely a lossy representation of this theory. &lt;strong&gt;In an era where LLMs can generate code, this distinction becomes critical: Who builds and maintains the mental model when AI writes the code?&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_semantic_anchors_the_bridge_between_humans_and_machines&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_semantic_anchors_the_bridge_between_humans_and_machines&quot;&gt;&lt;/a&gt;Semantic Anchors: The Bridge Between Humans and Machines&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;My second passion topic is semantic anchors for prompt optimization. When we work with LLMs, we need precise ways to communicate our mental model. Semantic anchors create this connection – they are the interface between human understanding and machine generation.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_todo_replace_human_coding_with_ai&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_todo_replace_human_coding_with_ai&quot;&gt;&lt;/a&gt;#TODO: Replace Human Coding With AI?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Avraham Poupko later delivered a fascinating deepening of the topic. In his talk &quot;#TODO: Replace Human Coding With AI,&quot; he presented his insights in an unprecedented chain of reasoning. His conclusions picked up on Naur&amp;#8217;s concepts and carried them forward into the era of AI-assisted development.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The central question: If LLMs can write code, what makes humans essential in the development process? The answer lies precisely in Naur&amp;#8217;s theory: building, understanding, and maintaining the mental model – something that LLMs fundamentally cannot accomplish.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_the_stochastic_parrot_understanding_limitations&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_the_stochastic_parrot_understanding_limitations&quot;&gt;&lt;/a&gt;The Stochastic Parrot: Understanding Limitations&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vaughn Vernon brought us back down to earth with his talk about the &quot;stochastic parrot.&quot; He emphasized the mathematics behind the models and explained from the LLMs&apos; functioning what they do well and what they do poorly.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;The term &quot;stochastic parrot&quot;&lt;/strong&gt; comes from the critique that LLMs probabilistically link words without truly understanding their meaning. For us architects, this means:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;✅ LLMs are excellent at pattern recognition and code generation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;❌ LLMs don&amp;#8217;t understand the &quot;why&quot; behind architectural decisions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;✅ They can create and search documentation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;❌ They cannot build genuine theory in Naur&amp;#8217;s sense&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vaughn&amp;#8217;s mathematically grounded perspective helped us understand the limitations and develop realistic expectations.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_the_fish_bowl_human_intelligence_vs_artificial_intelligence&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_the_fish_bowl_human_intelligence_vs_artificial_intelligence&quot;&gt;&lt;/a&gt;The Fish Bowl: Human Intelligence vs. Artificial Intelligence&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the evening, the discussion deepened in the Fish Bowl &quot;Software Architecture – Is It About Human Intelligence or Artificial Intelligence?&quot; with Vaughn Vernon, Cheryl Hung, Avraham Poupko, Eberhard Wolff, and participants from the audience.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The debate crystallized: &lt;strong&gt;It&amp;#8217;s not &quot;or&quot; but &quot;and&quot; – but with clear role distribution.&lt;/strong&gt; Human intelligence is irreplaceable in building the mental model, making architectural decisions under uncertainty, and understanding business contexts. AI becomes a powerful tool, an accelerator, but not a replacement.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_arc42_in_education_a_conversation_with_claudine_allen&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_arc42_in_education_a_conversation_with_claudine_allen&quot;&gt;&lt;/a&gt;arc42 in Education: A Conversation with Claudine Allen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A particular highlight was the talk by Claudine Allen from Jamaica. She reported how she teaches her students to use AI as a research and brainstorming tool for architecture work. She casually mentioned using arc42 in her work with students.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I was able to deepen this topic in the subsequent interview with her, which you can follow up on at &lt;a href=&quot;https://software-architektur.tv/&quot;&gt;software-architektur.tv&lt;/a&gt;. Claudine&amp;#8217;s approach impressively shows how the next generation of architects learns to use AI as a collaborative design partner – without forgetting the fundamental principles of good architecture work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Her students learn:&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;To use LLMs for research and exploration&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To critically question the results&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To build the mental model themselves&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To document in a structured way with arc42&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_my_core_theses&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_my_core_theses&quot;&gt;&lt;/a&gt;My Core Theses&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;After this intensive conference, the following theses crystallize for me:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_1_the_mental_model_remains_central&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_1_the_mental_model_remains_central&quot;&gt;&lt;/a&gt;1. The Mental Model Remains Central&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Naur&amp;#8217;s concept is more important than ever. While LLMs generate code, we humans must build and maintain the mental model. This is the non-delegable core competency of the software architect.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_2_semantic_anchors_as_key_technology&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_2_semantic_anchors_as_key_technology&quot;&gt;&lt;/a&gt;2. Semantic Anchors as Key Technology&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The way we communicate with LLMs determines the quality of the results. Semantic anchors – precise, context-rich prompts – are the bridge between our mental model and AI support.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_3_understand_dont_just_generate&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_3_understand_dont_just_generate&quot;&gt;&lt;/a&gt;3. Understand, Don&amp;#8217;t Just Generate&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The stochastic parrot can reproduce impressive patterns, but it doesn&amp;#8217;t understand. We need to know the limitations and work accordingly. LLMs are tools, not thinking partners.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_4_education_must_adapt&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_4_education_must_adapt&quot;&gt;&lt;/a&gt;4. Education Must Adapt&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Claudine&amp;#8217;s work shows the way: we must teach the next generation to use AI effectively without losing the ability to think independently.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_the_future_of_software_architecture&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#_the_future_of_software_architecture&quot;&gt;&lt;/a&gt;The Future of Software Architecture&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We stand at a fascinating turning point. GenAI and LLMs will fundamentally change the way we develop software. But they don&amp;#8217;t make the role of the architect obsolete – on the contrary.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;The architect of the future:&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Uses LLMs as powerful tools&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Builds and maintains the mental model of the system&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Makes decisions based on context not accessible to AI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Understands the limitations of the technology&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Communicates effectively with both machines and humans&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The Software Architecture Gathering 2024 showed: We need both the philosophical depth of a Peter Naur and the practical understanding of AI limitations. The synthesis of these perspectives will shape the software architecture of the future.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Further Resources:&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Peter Naur: &quot;Programming as Theory Building&quot; (1985)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;My interview with Claudine Allen at &lt;a href=&quot;https://software-architektur.tv/&quot;&gt;software-architektur.tv&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;arc42 Template: &lt;a href=&quot;https://arc42.org/&quot;&gt;arc42.org&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What do you think? How do you integrate LLMs into your architecture work without losing sight of the mental model?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph text-center&quot;&gt;
&lt;p&gt;#SoftwareArchitecture #GenAI #LLM #arc42 #iSAQB #SAG2024 #PeterNaur #AI #MachineLearning #SoftwareDevelopment&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>My MCP Setup</title>
      <link>https://fiveandahalfstars.ninja/blog/2025/2025-07-03-MCP-Setup.html</link>
      <pubDate>Thu, 3 Jul 2025 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2025/2025-07-03-MCP-Setup.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Oft werde ich gefragt, was für Tools ich bei der Arbeit mit LLMs verwende.
Hier ist meine Liste.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Als Chat nutze ich gerne Claude Desktop oder Claude Code.
Auch der Amazon Q Developer CLI ist spannend und Gemini CLI ist installiert, aber nicht getestet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;IDE basierte Systeme empfinde ich nicht so spannend.
Eine Zusammenarbeit über das File-System reicht mir aus.
Dabei greift der Chat über ein in einen Container gemountetes Working-Directory direkt auf das Projekt zu, das ich in einer IDE offen habe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dennoch habe ich auch Cursor als spannendes Experiment installiert.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_mcp_servers&quot;&gt;MCP Servers&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_filesystem_bash&quot;&gt;Filesystem &amp;amp; Bash&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Für Experimente ist ein Filesystem-MCP und ein Bash-MCP äussert nützlich.
Ich habe mir beide von Claude erstellen lassen.
Sie laufen in einem Container mit gemountetem Working-Directory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In der Bash sind wichtige Tools wie Git mit Account und gh installiert.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mein Filesystem-MCP hat eine Besonderheit.
Wenn das LLM einen Folder oder ein File anlegt, muss es angeben, wofür dieser Folder oder das File dient.
Schaut es sich in einer anderen Session die Files wieder an, bekommt es diese Meta-Daten auch wieder angezeigt.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_codeinterpreter&quot;&gt;Codeinterpreter&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Durch den Einsatz der Bash fällt der Codeinterpreter weg.
Das LLM kann alles direkt über die Bash erledigen.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_kroki&quot;&gt;Kroki&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Experimentell nutze ich ein Kroki-MCP, welches Diagramme generieren kann.
Ziel ist es, die Diagramme zuverlässig und in hoher Qualität zu erzeugen.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_gitmcp_io&quot;&gt;gitmcp.io&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Um den Knowledgegap der Modell zu überbrücken nutze ich gitmcp.io .
Um dem LLM die Dokumentation eines GitHub Projekts zur Verfügung zu stellen, muss man einfach nur in der URL github.com gegen gitmcp.io ausgetauscht werden.
Das Ergebnis ist eine URL für einen entsprechenden Remote-MCP-Server.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_sequential_thinking&quot;&gt;Sequential-Thinking&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Todo-Liste für das LLM.
Claude nutzt diesen MCP-Server gerne, um seine Gedanken zu strukturieren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;      &quot;Sequential-Thinking&quot;: {
        &quot;command&quot;: &quot;npx&quot;,
        &quot;args&quot;: [
          &quot;-y&quot;,
          &quot;@modelcontextprotocol/server-sequential-thinking&quot;
        ]
      }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_github&quot;&gt;GitHub&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;GitHub hat schon früh einen eigenen offiziellen MCP Server veröffentlicht.
Damit kann das LLM quasi alle Operationen durchführen.
Issues lesen und verändern, Forken, Files ändern, PR erstellen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Leider nutzt Claude momentan of dieses Tool, um Files zu editieren, ohne sie lokal zu testen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Der Umgang mit dem Git-Flow fällt Code auch nicht ganz leicht, weshalb ich ihm weitere Infos mitgebe:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;asciidoc&quot;&gt;### Git-Workflow:

✅ Richtig: main → branch → commit → push → PR
✅ starte einen neuen Branch für einen Bugfix immer als Feature-Branch vom Main-Branch
❌ Falsch: Parallele Branches ohne Synchronisation
✅ entscheide, ob ich claude als co-authored-by nenne

Achte immer auf folgendes, wenn Du mit Forks arbeitest
* Fork-Status prüfen
* Bei Bedarf synchronisieren
* Dann Branch + PR erstellen

Wenn Du mit source code arbeitest, sind wir immer unter versionskontrolle. Du brauchst keine Backup-Files anzulegen, sondern solltest mit commits arbeiten.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Da ich nicht möchte, dass Claude unter meinem Account arbeitet und somit Zugriff auf alles hat, habe ich einen neuen Account angelegt.
Das war eine gute Entscheidung.
So kann ich jederzeit sehen, was generiert worden ist.
Claude hat keinen direkten Zugriff auf meine Projekte und muss deshalb immer erst Forken und dann einen PR erstellen, den ich natürlich erst einem Review unterziehe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;      &quot;github&quot;: {
        &quot;command&quot;: &quot;docker&quot;,
        &quot;args&quot;: [
          &quot;run&quot;,
          &quot;-i&quot;,
          &quot;--rm&quot;,
          &quot;-e&quot;,
          &quot;GITHUB_PERSONAL_ACCESS_TOKEN&quot;,
          &quot;ghcr.io/github/github-mcp-server&quot;
        ],
        &quot;env&quot;: {
          &quot;comment&quot;: &quot;Raif Mueller Account&quot;,
          &quot;GITHUB_PERSONAL_ACCESS_TOKEN&quot;: &quot;ghp_xxx&quot;
        }
      }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_playwright_augen_für_das_llm&quot;&gt;playwright: Augen für das LLM&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Beim Arbeiten mit den LLMs ist es wichtig immer einen Feedback-Loop aufzubauen, damit das LLM eigenständig arbeiten kann.
Ein einfacher Weg für ein visuelles Feedback ist ein Browser.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/microsoft/playwright-mcp&quot;&gt;playwright-mcp&lt;/a&gt; von Microsoft ermöglicht es dem LLM nicht nur einen Browser fernzusteuern, sondern auch Screenshots zu &quot;sehen&quot;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Damit kann das LLM automatische visuelle Tests einer Website durchführen und auch generierte Bilder über die Darstellung im Browser verifizieren.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_responsible_vibe&quot;&gt;Responsible Vibe&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Oliver Jägle hat sich Gedanken gemacht, wie man das LLM dazu bringen kann, einen ordentlichen Entwicklungsprozess einzuhalten.
Herausgekommen ist sein &lt;a href=&quot;https://www.npmjs.com/package/responsible-vibe-mcp&quot;&gt;Responsible Vibe MCP&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&quot;responsible-vibe-mcp&quot;: {
  &quot;command&quot;: &quot;npx&quot;,
  &quot;args&quot;: [&quot;responsible-vibe-mcp&quot;]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_mcp_servers&quot;&gt;MCP Servers&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_filesystem_bash&quot;&gt;Filesystem &amp;amp; Bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_codeinterpreter&quot;&gt;Codeinterpreter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_kroki&quot;&gt;Kroki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_gitmcp_io&quot;&gt;gitmcp.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_sequential_thinking&quot;&gt;Sequential-Thinking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_github&quot;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_playwright_augen_für_das_llm&quot;&gt;playwright: Augen für das LLM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_responsible_vibe&quot;&gt;Responsible Vibe&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Richtig arbeiten mit dem LLM</title>
      <link>https://fiveandahalfstars.ninja/blog/2025/2025-01-08-Test-Driven-Development-With-LLM.html</link>
      <pubDate>Wed, 8 Jan 2025 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2025/2025-01-08-Test-Driven-Development-With-LLM.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In vielen Demos sehe ich, wie Jemand mit Tools wie Github Copilot zu Code Tests erzeugen lässt.
Das geht so schön einfach mit der Maschine und schnell hat man 100% Code-Coverage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Der Ansatz ist aber auf so vielen Ebenen falsch&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_development_driven_testing&quot;&gt;Development Driven Testing?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wollten wir nicht Test-Driven-Development machen?
Wenn wir Tests zum Code schreiben, laufen wir Gefahr, dass wir die innere Mechanik unseres Codes testen und nicht das Verhalten!
Wir sehen, was der Code macht und fangen an genau dafür Tests zu schreiben.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein falsches Verhalten im Edge-Case?
Der Test fixiert den Bug!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Eine bestimmte Implementierung?
Der Test, der die Implementierung testet und nicht das Verhalten, wird später ein Refactoring erschweren!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_white_board_development&quot;&gt;White-Board-Development&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Aber der wichtigste Grund, nicht die Tests für den Code schreiben zu lassen ist, was ich als White-Board-Development bezeichne.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wenn Du einen Algorithmus an einem Whiteboard entwerfen sollst, wie hoch ist die Wahrscheinlichkeit, dass der Code auf Anhieb fehlerfrei läuft?
Genau - sehr gering.
Aber von der Maschine erwarten wir es!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wie gehen wir stattdessen vor?
Wir nutzen unsere Lieblings-IDE und führen den Code aus, bemerken den ersten Syntax-Fehler und verbessern den Code.
So iterieren wir, bis der Code läuft.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein LLM kann das über function-calling auch.
Es muss nur das richtige Tool zur Verfügung gestellt bekommen.
Im Fall von ChatGPT ist das der Python Code Interpreter&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_development_driven_testing&quot;&gt;Development Driven Testing?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_white_board_development&quot;&gt;White-Board-Development&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Elgato Prompter: 2 Überraschungen, die du kennen musst 🎥🖥️</title>
      <link>https://fiveandahalfstars.ninja/blog/2024/2024-10-18-teleprompter.html</link>
      <pubDate>Fri, 18 Oct 2024 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2024/2024-10-18-teleprompter.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
Links sind Affiliate-Links
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Letzte Woche habe ich mir den &lt;a href=&quot;https://amzn.to/3A4ByZl&quot;&gt;Elgato Prompter&lt;/a&gt; zugelegt. Elgato ist bekannt für seine Qualität – und entsprechende Preise. Die Erwartungen waren hoch, insbesondere aufgrund des eingebauten Bildschirms mit USB-C-Anschluss. Doch ich wurde schnell überrascht, nicht nur im positiven Sinne.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2024/prompter.jpg&quot; alt=&quot;prompter&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_displaylink_statt_displayport_ein_unerwarteter_stolperstein&quot;&gt;DisplayLink statt DisplayPort – Ein unerwarteter Stolperstein 🔌&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zunächst hätte ich erwartet, dass der Bildschirm über den nativen DisplayPort des USB-C-Anschlusses läuft. Stattdessen wird er jedoch über &lt;strong&gt;DisplayLink&lt;/strong&gt; angesteuert, ein Protokoll, das zusätzliche Treiber erfordert. Die Installation dieser Treiber verlangt &lt;strong&gt;Administrationsrechte&lt;/strong&gt;, die in Unternehmensumgebungen nicht immer zur Verfügung stehen. Noch schlimmer: Abhängigkeit von Treibern bedeutet auch, dass ein neues Betriebssystem und nicht mehr gepflegte Treiber das Produkt irgendwann unbrauchbar machen könnten. Da setze ich lieber auf gesetzte Standards.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_die_enttäuschung_über_die_auflösung&quot;&gt;Die Enttäuschung über die Auflösung 🧱&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein weiterer überraschender Punkt war die &lt;strong&gt;Auflösung&lt;/strong&gt; des Bildschirms: Sie liegt bei nur &lt;strong&gt;1024 x 600 Pixeln&lt;/strong&gt;. Für meine Hauptanwendung, Präsentationen auf dem Prompter anzuzeigen, führt das zu einem Problem. Der Bildschirm kann nicht direkt geteilt werden, da die schlechte Auflösung die Qualität beeinträchtigt und Aufnahmen darunter leiden würden.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_macos_vs_windows_ein_skalierungskrieg&quot;&gt;MacOS vs. Windows – Ein Skalierungskrieg 🍏🪟&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Sache wird noch komplexer, wenn man den Unterschied zwischen &lt;strong&gt;MacOS&lt;/strong&gt; und &lt;strong&gt;Windows&lt;/strong&gt; betrachtet. Unter MacOS gibt es nur die native Bildschirmauflösung, ohne Möglichkeit einer individuellen Skalierung für unterschiedliche Displays. Da ich einen 4k Monitor und das eingebaute hochauflösende Display normalerweise verwende, ist in manden Programmen wie MS-Teams das UI durch die Anwendung vergrößert. Das bedeutet wiederum, dass UI-Elemente auf dem Prompter &lt;strong&gt;unverhältnismäßig groß&lt;/strong&gt; dargestellt werden, wodurch kaum Platz für den eigentlichen Inhalt bleibt. Das Problem liegt darin, dass MacOS standardmäßig alle Bildschirme gleich behandelt, was bei einem so niedrig auflösenden Display wie dem Prompter zu Darstellungsproblemen führt. Auf Windows kann ich hingegen einen &lt;strong&gt;Skalierungsfaktor&lt;/strong&gt; pro Display einstellen, was die Darstellung deutlich verbessert. Allerdings funktioniert diese Skalierung nur imBereich von 100-500% - ich bekomme nicht mehr auf den kleinen Bildschirm, sondern eher weniger.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_der_gescheiterte_spiegelungsversuch&quot;&gt;Der gescheiterte Spiegelungsversuch 🔄&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Natürlich dachte ich, ich könnte einen meiner anderen Bildschirme (Notebook oder externes 4K-Display) einfach auf den Prompter spiegeln. Leider blieb der Prompter unter MacOS schwarz – die Auflösung des zu spiegelnden Hauptdisplays war einfach zu hoch.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_meine_spezielle_lösung_hdmi_dummy_stecker&quot;&gt;Meine spezielle Lösung – HDMI-Dummy Stecker 🧩&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Am Ende fand ich eine Lösung, die zwar ungewöhnlich ist, aber hervorragend funktioniert: Ich verwende &lt;a href=&quot;https://amzn.to/4dRRz2w&quot;&gt;&lt;strong&gt;HDMI-Dummy-Stecker&lt;/strong&gt;&lt;/a&gt;, die einen HDMI-Monitor simulieren. So kann ich unter &lt;strong&gt;Windows und MacOS&lt;/strong&gt; eine höhere Auflösung wie &lt;strong&gt;1920 x 1080 Pixel (Full HD)&lt;/strong&gt; auf dem dummy-Monitor einstellen und dann dieses virtuelle Display auf den Prompter spiegeln. Mit dieser Lösung erhalte ich eine skalierte Full-HD-Auflösung, die perfekt für die Darstellung von UI-Elementen ist und eine gute Qualität beim Teilen des Bildschirms ermöglicht.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_update_30_04_2025&quot;&gt;Update 30.04.2025&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Gestern konnte ich zwei weitere interessante erfahrungen machen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Den Prompter nutze ich mittlerweile nur noch unter Windows,
denn ich nutze eine Canon Spiegelreflex als Kamera.
Die Treiber funktionieren nicht mehr mit Apple-Silicon und eine andere Kamera möchte ich momentan nicht einsetzen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_schwarze_balken_ohne_hdmi_dummy&quot;&gt;Schwarze Balken ohne HDMI-Dummy&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Den HDMI-Dummy Stecker benötige ich unter Windows nicht unbedingt.
Ich kann auch mein normales Display spiegel.
Der Dummy-Stecker sorgt für weiteren Aufwand in meiner eh schon recht komplexen Verkabelung.
Allerdings habe ich dann keine 16:9 Auflösung, die aber von meinen Slides erwartet wird.
Dadurch ergeben sich beim Screensharing schwarze Balken&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_elgato_camera_hub&quot;&gt;Elgato Camera Hub&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein zweites Problem ist das helle Design meiner Slides.
Das Display strahlt tatsächlich in die Kamera, wodurch ich blass rüber komme.
Die Lösung ist, das Display zu dimmen.
Allerdings hat der Elgato Camera Hub, mit dem man solche Einstellungen vornehmen kann, das Display nicht erkannt.
Die unerwartete Lösung war, dass der Camera Hub das Display nur erkennt, wenn es nicht gespiegelt genutzt wird.
Also erstmal die Displays wieder getrennt, dann das Display gedimmt, dann wieder das Hauptdisplay gespiegelt.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_displaylink_statt_displayport_ein_unerwarteter_stolperstein&quot;&gt;DisplayLink statt DisplayPort – Ein unerwarteter Stolperstein 🔌&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_die_enttäuschung_über_die_auflösung&quot;&gt;Die Enttäuschung über die Auflösung 🧱&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_macos_vs_windows_ein_skalierungskrieg&quot;&gt;MacOS vs. Windows – Ein Skalierungskrieg 🍏🪟&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_der_gescheiterte_spiegelungsversuch&quot;&gt;Der gescheiterte Spiegelungsversuch 🔄&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_meine_spezielle_lösung_hdmi_dummy_stecker&quot;&gt;Meine spezielle Lösung – HDMI-Dummy Stecker 🧩&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_update_30_04_2025&quot;&gt;Update 30.04.2025&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_schwarze_balken_ohne_hdmi_dummy&quot;&gt;Schwarze Balken ohne HDMI-Dummy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_elgato_camera_hub&quot;&gt;Elgato Camera Hub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>iX: "Künstliche Intelligenz in der Softwarearchitektur praktisch einsetzen"</title>
      <link>https://fiveandahalfstars.ninja/blog/2024/2024-09-09-ix.html</link>
      <pubDate>Mon, 9 Sep 2024 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2024/2024-09-09-ix.html</guid>
      <description>
      &lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_künstliche_intelligenz_in_der_softwarearchitektur_praktisch_einsetzen&quot;&gt;Künstliche Intelligenz in der Softwarearchitektur praktisch einsetzen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Künstliche Intelligenz macht Softwarearchitektur und kann Architektinnen und Architekten auf vielfältige Weise bei Entwurf, Prüfung oder Diagramm unterstützen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein neuer Artikel für das Architektur-Sonderheft der iX.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.heise.de/hintergrund/Kuenstliche-Intelligenz-in-der-Softwarearchitektur-praktisch-einsetzen-9849104.html&quot;&gt;weiterlesen&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_künstliche_intelligenz_in_der_softwarearchitektur_praktisch_einsetzen&quot;&gt;Künstliche Intelligenz in der Softwarearchitektur praktisch einsetzen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Softwarearchitektur: "KI wird unsere Fähigkeiten ergänzen, nicht ersetzen"</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-10-22-isaqb.html</link>
      <pubDate>Sun, 22 Oct 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-10-22-isaqb.html</guid>
      <description>
      &lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_software_architektur_und_chatgpt&quot;&gt;Software-Architektur und ChatGPT&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wie wird sich die Arbeit eines Software-Architekten mit KI verändern?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ich probiere es aus und wage einen Blick in die Glaskugel&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.heise.de/hintergrund/Softwarearchitektur-KI-wird-unsere-Faehigkeiten-ergaenzen-nicht-ersetzen-9339113.html&quot;&gt;(M)ein Interview auf heise.de&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_software_architektur_und_chatgpt&quot;&gt;Software-Architektur und ChatGPT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Software architecture: "AI will complement our skills, not replace them".</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-10-22-isaqb-en.html</link>
      <pubDate>Sun, 22 Oct 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-10-22-isaqb-en.html</guid>
      <description>
      &lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_software_architecture_and_chatgpt&quot;&gt;Software-Architecture and ChatGPT&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;How will the work of a software architect change with AI?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I try it out and dare a look into the crystal ball&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://conferences.isaqb.org/software-architecture-gathering/transforming-software-architecture-exams-chatgpt-as-your-strategic-ally-for-success-an-interview-with-ralf-d-mueller/&quot;&gt;read my interview on isaqb.org&lt;/a&gt;&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_software_architecture_and_chatgpt&quot;&gt;Software-Architecture and ChatGPT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Speed up your Podcast Editing with Generative AI (Developer Advocate Version)</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-09-21-speedup-podcast-production-developer-advocate-version.html</link>
      <pubDate>Thu, 21 Sep 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-09-21-speedup-podcast-production-developer-advocate-version.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/speed-up-podcast-production-cover.jpg&quot; alt=&quot;speed up podcast production cover&quot; width=&quot;60%&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Recording and editing a podcast is a lot of fun. There is something special talking to each other and exchanging ideas, have a laugh and producing an artifact that potentially a lot of people can listen to to get some value.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Thus said it is also a ton of work!&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For producing the first season of &lt;a href=&quot;https://podcasters.spotify.com/pod/show/jandjtalkai&quot;&gt;J&amp;amp;J Talk AI&lt;/a&gt; I did nearly everything manually except the transcription where I used &lt;a href=&quot;https://fiveandahalfstars.ninja/blog/2023/2023-03-20-create-subtitles-with-whisperai&quot;&gt;Whisper (I wrote an article about that)&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For season 2 I wanted to automate as much as I could to reduce the time I have to spend with tedious tasks like writing a full transcription with nice formatting and speaker labels, creating a podcast description and social media posts. Furthermore I wanted to get rid of much of the postproduction stuff like silences, stutter or filler words.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So this blog post contains all the learnings which in sum reduced my editing/postproduction time to about 50% of what it was before - conservative estimation 🦄.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_recording_platform&quot;&gt;Recording Platform&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For recording a podcast there is no way around an online recording solution now, because they record locally for every participant and upload the recording afterwards. This guarantees the best audio quality where nobody has a big hassle with their local setup except getting their microphone to work 😉.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_riverside_fm&quot;&gt;Riverside.fm&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For the first two seasons we used &lt;a href=&quot;https://riverside.fm/homepage&quot;&gt;Riverside.fm&lt;/a&gt; as they offer a generous two hour recording limit for separated tracks.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;They also offer some unique features like Magic-Clips creation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Overall I liked the experience as the setup was easy. If you also want to edit inside a browser and get a transcript for free, Riverside.fm is your place to go.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The only downside I found and that might be specific to me was that the exported quality lacked. At least for my voice I had overly loud white noise and also the sound level was way to high in every recording. By cleaning it up my voice suffered which is a real bummer as the sound quality is excellent when I record locally 😕.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_streamyard&quot;&gt;Streamyard&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://streamyard.com/&quot;&gt;Streamyard&lt;/a&gt;&amp;#8201;&amp;#8212;&amp;#8201;as the name implies&amp;#8201;&amp;#8212;&amp;#8201;is designed for streaming. But it also has a recording feature which records locally.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Setup is fairly easy and straightforward making it an alternative to Riverside.fm if you do not need all the fancy features.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Also the audio quality seems to be a tick better in my opinion. And actually that is all I care about!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_descripts_squadcast&quot;&gt;Descripts Squadcast&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: I did not try Squadcast yet as I exhausted my free minutes with a transcription 🙃&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://squadcast.fm/&quot;&gt;Squadcast&lt;/a&gt; looks like Riverside.fm and Streamyard when it comes to features. The real gamechanger comes with the integration of Descript (See later in the article).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Having a recording solution where you do not have to import the recording into another tool looks like a no brainer to me.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_editing&quot;&gt;Editing&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Editing a podcast can be a daunting task. Not only do you have to cut silence, filler words, stuttering and mouth sounds.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You also have to normalize audio levels and apply some voice filters to make the voices sound professional.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Surely there are a lot of tools out there that can help with that, right? Right?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And yes there are a ton of tools out there that you can try for free to see what helps in your particular situation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Note: Your recording setup may be different and thus your recording quality you start with different than mine. Take this into account when you read the reviews.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_auphonic&quot;&gt;Auphonic&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://auphonic.com/&quot;&gt;Auphonic&lt;/a&gt; looks extremely strong when you look at the features. Except from removing filler words it should be your one-shot solution to produce great audio.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Also the demos are impressive and I could not wait to try it out.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But unfortunately I could not make it work in my case. I experienced the following issues:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Noise was not removed completely&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Normalization put too much gain on my voice&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Loudness levels where not applied&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What worked well:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Silence removal&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Auto-EQ.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_adobe_podcaster_enhancer&quot;&gt;Adobe Podcaster Enhancer&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://podcast.adobe.com/enhance&quot;&gt;Adobe Podcaster&lt;/a&gt; offers a free audio enhancer where you can remove noise and echo from your audio, but not filler sounds and stuttering.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For me it did fail on:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Noise removal - Still noticable&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But it did a great job enhancing the audio. Both voices felt rich after enhancing.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_ai_coustics&quot;&gt;AI-Coustics&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://ai-coustics.com/&quot;&gt;AI-coustics&lt;/a&gt; did a great job at removing noise. It was gone and the voices still sounded nice.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The only problem I noticed was that sometimes the volume levels dipped a little bit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you have heavy background noise I would probably use AI-coustics as in my opinion it did the best job with noise removal.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_audo_ai&quot;&gt;Audo-AI&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://audo.ai/&quot;&gt;Audo.AI&lt;/a&gt; did a similar good job with the audio quality like AI-coustics. But a little bit of background noise was noticable.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_descript&quot;&gt;Descript&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If I would create video or audio content every week I would definitely purchase &lt;a href=&quot;https://www.descript.com/&quot;&gt;Descript&lt;/a&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The editing is a completely different experience: You edit on the transcript! And then the audio adapts to that 🤯.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Removing specific filler words is a Search+Replace away. Getting rid of silence is also well done: You specify the gap width that should be shortened and to what it should be reduced.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Also the sound quality is great. No background noise hearable in my case.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_cleanvoice&quot;&gt;Cleanvoice&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For now I stuck with &lt;a href=&quot;https://cleanvoice.ai/&quot;&gt;Cleanvoice&lt;/a&gt; because they have a credit based payment model. I purchased the credits and can use it any time I want.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The best thing about Cleanvoice is that it removes filler words, stuttering, background noise and silence automatically. Although you still have to edit a little bit, because automation makes mistakes 😉.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I had to invest about 15 minutes of additional editing per episode to get the same result as with Descript. Which is ok when you are only casually podcasting.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_what_should_i_use&quot;&gt;What Should I Use?&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you have the money for it I highly recommend Descript. The different approach to editing is intuitive and fast and the audio quality is top notch.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For now I use Cleanvoice as it is pay-what-you-use and the audio quality is as high as Descripts.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_transcription&quot;&gt;Transcription&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A transcript of the recording is a nice way to reuse your content and also to make it accessible to everyone. For transcribing text I use &lt;a href=&quot;https://fiveandahalfstars.ninja/blog/2023/2023-03-20-create-subtitles-with-whisperai&quot;&gt;Whisper (I wrote an article about that)&lt;/a&gt; locally. But you can also use any transcription service out there.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;At least for the raw transcription this seems to be a solved problem. The &lt;strong&gt;medium&lt;/strong&gt; model from Whisper produces nearly no errors. So I have to do only a few minutes of correction on each episode.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A raw transcription is nice if you want to feed it into a Large Language Model (LLM) like chatGPT. But it does not make for nice to read content because it misses two things:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nice formatting&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Speaker diarisation (Labels which speaker is speaking)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I was not able to try out some tools for the latter, but &lt;a href=&quot;https://github.com/MahmoudAshraf97/whisper-diarization&quot;&gt;this Github repository looks promising&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_diarisation&quot;&gt;Diarisation&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So to get my speaker labels I did the diarisation manually and every time the speaker changes I added an empty line. The transcripts look like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Hello and welcome to J&amp;amp;J Talk AI. Today we are talking...

Hey there. Nice to be back gain!

The topic of this episode is...

Yeah, so...&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_generating_speaker_labels_automatically_with_chatgpt&quot;&gt;Generating Speaker Labels Automatically with chatGPT&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I then fed the diarised output to chatGPT with a prompt to add the speaker labels.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Note: This only works well if you have two speakers that naturally alternate.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The prompt looks like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Heyho, can you help me with a tedious task please.

So I have this long transcript of a podcast and I need you to add labels to a file. Here is an example:

JH: Yeah this is a podcast
JD: Welcome to it.

The labels are JH: and JD:

You can identify the blocks by an empty line. It starts with JD: and the next block with JH: and then it alternates between these two. Also do not label the blocks in any way please. Make sure the first block starts with JD: .

Here is the transcript:&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This worked for me, although sometimes I got the modified transcript as a codesnippet 😋.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_generating_content&quot;&gt;Generating Content&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For generating further content I used chatGPT-3.5 which can handle the longer transcripts and works decently now.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The results where sometimes of mixed quality and I &lt;em&gt;highly&lt;/em&gt; recommend to proofread them and give them a personal touch.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But the speedup at this stage for creating a podcast description, a LinkedIn post and a social messenger post, was fairly impressive. For the five episodes I needed about &lt;strong&gt;two&lt;/strong&gt; hours of work to get the quality I wanted.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Last time this took me &lt;strong&gt;five&lt;/strong&gt; hours which is an impressive speedup 🥳.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the next section I will share my prompts and the reasoning behind it. I didn&amp;#8217;t do much prompt engineering to be honest. Just some basic things I picked up in the last weeks. If someone wants to improve on them let me know what worked for you.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_podcast_description&quot;&gt;Podcast description&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The prompt for the podcast description took some attempts. The model picked up on a lot of content in the transcript you do not want to be in a podcast description.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For example sponsor messages were included every time and also the opening lines. Especially annoying is the tendency to include a huge amount of emojis and add things that were not in the transcript at all.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I made sure to add instructions not to add superfluous stuff and to be concise.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Heyho I want you to act as a Developer Advocate who is great at social media. The things you write should not be markety but should be engaging.

I want you to create a podcast description out of the text I provide. Keep the length short and to the point. Also do not use any emojis and direct quotations from the text I provide. Please take only content out of the text. No sponsor messages!

Here is the text:&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_social_media_short_message_and_linkedin&quot;&gt;Social Media: Short Message and LinkedIn&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In social media I want some emojis so I made sure only some are there. Also again sponsor messages should not be included. But overall the results where great and I had to do only minimal editing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Heyho I want you to act as a Developer Advocate who is great at social media. The things you write should not be markety but should be engaging.

I want you to create a Twitter post out of the text I provide. Do not overly use emojis and keep the tweet under 160 characters. Please take only content out of the text. No sponsor messages!

Here is the text:&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;LinkedIn looks nearly the same but without the character limit and the instruction to keep it brief:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Heyho I want you to act as a Developer Advocate who is great at social media. The things you write should not be markety but should be engaging.

I want you to create a LinkedIn Post out of the text I provide. Do not overly use emojis and keep it somewhat brief. Please take only content out of the text. No sponsor messages!

Here is the text:&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect3&quot;&gt;
&lt;h4 id=&quot;_blogpost&quot;&gt;Blogpost&lt;/h4&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For the blog post I had to put the diarised and speaker labeled transcript into a WYSIWYG-Editor which works, but is not optimal. There was one particular problem:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bolden&lt;/strong&gt; the speaker labels&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Which is an easy Search+Replace in Markdown or AsciiDoc. But not in an WYSIWYG-Editor with no such feature.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Thus I tried to automate this using &lt;a href=&quot;https://www.askui.com/blog-posts/automate-highlighting-in-wysiwyg-editors&quot;&gt;AskUI which worked decently in this case&lt;/a&gt;. Not faster, but less straining on my wrists 🦾.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;My little experiments in automating a lot of things around my podcast were a lot of fun and brought a lot of insights on how to speed up things with AI/ML.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I managed to shave off a good amount of time for all the tasks.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Thus said, using Large Language Models like chatGPT still requires a lot of finesse and the results need editing. I would not try to fully automate everything if quality is important&amp;#8230;&amp;#8203; Yet! 😇&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@soundtrap?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot;&gt;Soundtrap&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_recording_platform&quot;&gt;Recording Platform&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_riverside_fm&quot;&gt;Riverside.fm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_streamyard&quot;&gt;Streamyard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_descripts_squadcast&quot;&gt;Descripts Squadcast&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_editing&quot;&gt;Editing&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_auphonic&quot;&gt;Auphonic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_adobe_podcaster_enhancer&quot;&gt;Adobe Podcaster Enhancer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_ai_coustics&quot;&gt;AI-Coustics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_audo_ai&quot;&gt;Audo-AI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_descript&quot;&gt;Descript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_cleanvoice&quot;&gt;Cleanvoice&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_transcription&quot;&gt;Transcription&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_diarisation&quot;&gt;Diarisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_generating_speaker_labels_automatically_with_chatgpt&quot;&gt;Generating Speaker Labels Automatically with chatGPT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_generating_content&quot;&gt;Generating Content&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>A Comprehensive DevRel Metrics Guide (Part 4): Company Stages and Reporting</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-09-17-a-comprehensive-devrel-metrics-guide-part4.html</link>
      <pubDate>Sun, 17 Sep 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-09-17-a-comprehensive-devrel-metrics-guide-part4.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/comprehensive-devrel-metrics-guide-part4-cover.jpg&quot; alt=&quot;comprehensive devrel metrics guide part4 cover&quot; width=&quot;60%&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Imagine you are working at an early stage startup and you are tasked with tracking meaningful metrics. And then imagine you are working at an enterprise company with the same task.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Would you track the same metrics?&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I have been scratching my head over this question because it does not make sense to me that the metrics should be the same for both companies 🤔.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_what_company_stages_are_there&quot;&gt;What Company Stages Are There?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I found an &lt;a href=&quot;https://www.youtube.com/watch?v=KXGXfbQfrrI&quot;&gt;inspiring talk from Vera Tiago&lt;/a&gt; that resonated with me. There is also &lt;a href=&quot;https://vera-tiago.medium.com/northstar-metrics-and-okrs-to-show-devrel-value-and-get-focus-92fb058f3e1a&quot;&gt;a written form of it&lt;/a&gt;, if that is more your thing 🥰.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In there she talks about North Star metrics and then comes to the topic of DevRel-Focus areas. Her Developer Relations focus areas are:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Awareness&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adoption&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Education&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Retention&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And then she makes an interesting distinction between two areas you have to look at as a company:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Maturity of your product&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Maturity of your community&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So if you are an early stage startup you probably have an &lt;em&gt;unmature&lt;/em&gt; product and a just &lt;em&gt;forming&lt;/em&gt; community. Thus working towards retention may not be your highest priority as your product has to many kinks and your community is too small.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It should be better to work towards acquisition and adoption to get more users.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;By doing this you get more feedback and exposure to achieve product market fit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/vera_tiago_where_to_focus.png&quot; alt=&quot;Reach&quot; width=&quot;80%&quot; height=&quot;Engagement and DevRel Qualified Leads in this order in a horizontal pyramid. Decreasing breadth from left to right and increasing depth from left to right.&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. Vera Tiagos four pillars of DevRel and company stage (Source (&lt;a href=&quot;https://vera-tiago.medium.com/northstar-metrics-and-okrs-to-show-devrel-value-and-get-focus-92fb058f3e1a&quot;&gt;a written form of it&lt;/a&gt;))&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Evaluating and validating your company&amp;#8217;s stage and your focus with management is extremely important as it again will determine the metrics you are prioritizing.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_how_to_do_reporting&quot;&gt;How to Do Reporting?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Many companies have a monthly All-Hands meeting. Some call it a Jour-Fix. Whatever you call it, entering your collected data into a nice presentation template gives you the possibility to always be ready to give a presentation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I do not get into all the details in the presentation deck but focus on the things that matter now. Even when I track more than that as outlined in the previous blog post. There is a dedicated slide at the end where I link to the raw metrics if anyone is interested in them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With the slide deck I am good to go to present 5-10 Minutes and give a concise update about how we are doing 🎉&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here is &lt;a href=&quot;https://docs.google.com/presentation/d/1rdYEUbZWYPi7tVBbx5YRF78n1GdJDHHP8tCQ3piydL4/edit?usp=sharing&quot;&gt;my template as a Google-Slide Deck&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And this marks the end of this series. We discussed why metrics are important, where to even start and my personal view on what metrics to track.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In this blog post I gave an introduction on what might be important and expected from DevRel at different company stages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As always: Do not blindly follow advice but take it as a food for thought and an idea to test in your circumstance! I feel this is especially important in DevRel as no company is the same 🙃.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@andretaissin?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot;&gt;Andre Taissin&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_what_company_stages_are_there&quot;&gt;What Company Stages Are There?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_how_to_do_reporting&quot;&gt;How to Do Reporting?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>A Comprehensive DevRel Metrics Guide (Part 3): A Framework to Get Started!</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-06-15-a-comprehensive-devrel-metrics-guide-part3.html</link>
      <pubDate>Fri, 16 Jun 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-06-15-a-comprehensive-devrel-metrics-guide-part3.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/comprehensive-devrel-metrics-guide-part3-cover.jpg&quot; alt=&quot;comprehensive devrel metrics guide part3 cover&quot; width=&quot;60%&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In &lt;a href=&quot;https://fiveandahalfstars.ninja/blog/2023/2023-06-05-a-comprehensive-devrel-metrics-guide-part2.html&quot;&gt;part two of the series&lt;/a&gt; we discussed what DevRel north star metrics commonly get used across the industry. We also saw that it can be quite tricky to find the right metrics to measure because they are plenty, sometimes lag behind or the relation to your North Star is not direct but only delivered over time.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;So what should we do?&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I will answer this question in this article for people who are just starting out and looking for a way to have a solid foundation to build on. Because that is what I found myself in when I started my Developer Advocate journey 😊.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But also if you have something in place already. This article will help you make sense of metrics and give you inspiration.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_the_solid_framework_kim_maidas_keystone_framework&quot;&gt;The Solid Framework: Kim Maidas Keystone Framework&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Just starting out with DevRel-Metrics? Look no further than Kim Maidas &lt;strong&gt;DevRel Metrics Keystone Framework&lt;/strong&gt;. Over the course of her career leading in Developer Relations she says she found a way to holistically measure DevRel in a way the C-Suite understands. And I could not agree more!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/kim-maida-keystone-devrel-metrics-horizontal.png&quot; alt=&quot;Reach, Awareness, Engagement and DevRel Qualified Leads in this order in a horizontal pyramid. Decreasing breadth from left to right and increasing depth from left to right.&quot; width=&quot;90%&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. Kim Maidas Keystone DevRel Metrics (Source: &lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations&quot;&gt;Kim Maidas article&lt;/a&gt;)&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Her idea is to define one &lt;em&gt;Keystone&lt;/em&gt; (North Star) as your guidance. Her recommended keystone is &lt;strong&gt;1 signup/registration&lt;/strong&gt;. Ideally it is your company&amp;#8217;s North Star.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Once you have your keystone you can come up with a price tag for it. Yes, real money!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Then with a price tag you can attach a percentage of this keystone value to each metric in the following categories:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations/#ib-toc-anchor-9&quot;&gt;Reach&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations/#ib-toc-anchor-12&quot;&gt;Awareness&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations/#ib-toc-anchor-15&quot;&gt;Engagement&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations/#ib-toc-anchor-18&quot;&gt;DevRel Qualified Leads&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There is an order to it also. &lt;em&gt;Reach&lt;/em&gt; metrics are at the top of the funnel and thus improving metrics from that category is not as valuable as further down the funnel. &lt;em&gt;Engagement&lt;/em&gt; and finally &lt;em&gt;DevRel Qualified Leads&lt;/em&gt; are worth so much more and you can add more value to each metric in those categories.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What you basically do is attaching a value tag on every metric and are thus able to calculate the value DevRel brings to the table 🥳.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I do not want to copy &lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations&quot;&gt;Kim Maidas article&lt;/a&gt;, so for the sake of brevity, I encourage you to read it and use her method to give every metric a meaning tied to company metrics.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There is also much more in her article that makes the read worthwile!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_my_personal_additions&quot;&gt;My Personal Additions&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I personally found two additions helpful in showing impact on product/engineering:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Internal Impact&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Direct Impact&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The first one captures the feedback you bring from the community into the company. The second one measures your direct impact you have by doing developer experience audits and creating content.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_internal_impact&quot;&gt;Internal Impact&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In my daily work a lot of things I do are related to product development. Be it providing feedback for new features, betatesting new features, writing docs, gathering feedback from the community and relaying it back to development. The above areas do not cover them completely.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Luckily I found two articles that cover these areas well (See &lt;a href=&quot;https://thefalc.com/2020/12/devrel-metrics-and-why-they-matter/&quot;&gt;Sean Falconers - DevRel Metrics And Why They Matter&lt;/a&gt;) and &lt;a href=&quot;https://medium.com/google-developers/the-core-competencies-of-developer-relations-f3e1c04c0f5b&quot;&gt;The Core competencies of Developer Relations by Reto Meier&lt;/a&gt;. They talk about the developer relations cycle where they introduce &lt;em&gt;Developer Feedback&lt;/em&gt; and &lt;em&gt;Developer Sentiment&lt;/em&gt; that Developer Relations collects and brings into product development.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/reto-meier-core-competencies-of-devrel.png&quot; alt=&quot;Developer Relations Cycle: Platform &amp;amp; Engineering putting out features for your product and receiving developer feedback. Developer Relations as middlehuman to spread awareness and put out resources for the developer community. Also receiving developer feedback and sentiment.&quot; width=&quot;90%&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 2. The Developer Relations ongoing interface cycle (Source: &lt;a href=&quot;https://medium.com/google-developers/the-core-competencies-of-developer-relations-f3e1c04c0f5b&quot;&gt;The Core competencies of Developer Relations by Reto Meier&lt;/a&gt;)&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As you are acting as a middlehuman for these two, I call this &lt;em&gt;internal impact&lt;/em&gt; as you affect your product through the feedback delivered.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What I like to measure here is the number of feedback and sentiment brought to the department in your company where it is best seated. If anything comes out of this feedback that is also noted down.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_direct_impact&quot;&gt;Direct Impact&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As you have noticed, most metrics are loosely tied to company goals. But there are ways to demonstrate a direct impact. Things I found useful are the following:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer Experience Audits&lt;/strong&gt;: Evaluating your product as a user would and providing detailed feedback and improvement suggestions to product management. You should also track what is finally implemented and if possible if any metric was impacted by the change (Less bug-tickets for example or specific user complaints decreasing).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tracking your content&amp;#8217;s impact&lt;/strong&gt;: With sufficient tracking in place you can track if your company&amp;#8217;s North Star metric is affected by your content like docs, blogs or videos. In fact this is what I do and I could demonstrate that videos on YouTube drive Sign Ups.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_conclusion_part_3&quot;&gt;Conclusion Part 3&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With a framework like the one from Kim Maida you can lay a solid foundation for all your metric needs in a structured way. It also makes reporting easier by directly tying individual metrics to your companies north star.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the last part of the series we will dive into the wonderful world of company development stages and their individual needs from DevRel. Early stage startups are different than enterprise organizations. And there is a lot of space in between.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Thus we should shift our focus and the metrics we take into focus accordingly.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I will also share my template I use to report DevRel metrics every month.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Photo by Leonardo Vazquez: &lt;a href=&quot;https://www.pexels.com/photo/scales-with-berries-and-organic-ingredients-for-recipe-3743169/&quot;&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_the_solid_framework_kim_maidas_keystone_framework&quot;&gt;The Solid Framework: Kim Maidas Keystone Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_my_personal_additions&quot;&gt;My Personal Additions&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_internal_impact&quot;&gt;Internal Impact&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_direct_impact&quot;&gt;Direct Impact&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_conclusion_part_3&quot;&gt;Conclusion Part 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>A Comprehensive DevRel Metrics Guide (Part 2): What DevRel Metrics should I track?</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-06-05-a-comprehensive-devrel-metrics-guide-part2.html</link>
      <pubDate>Wed, 7 Jun 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-06-05-a-comprehensive-devrel-metrics-guide-part2.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/comprehensive-devrel-metrics-guide-part2-cover.jpg&quot; alt=&quot;comprehensive devrel metrics guide part2 cover&quot; width=&quot;60%&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now that we got the &lt;strong&gt;Why?&lt;/strong&gt; out of the way &lt;a href=&quot;https://fiveandahalfstars.ninja/blog/2023/2023-06-01-a-comprehensive-devrel-metrics-guide-part1.html&quot;&gt;in part 1&lt;/a&gt;. Let&amp;#8217;s face the difficult challenge on what DevRel Metrics we should collect in the first place.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Of course I will stand on the shoulders of giants here again as a lot of smart DevRel-practitioners have already written about this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The goal of this post is to get to a common understanding what others usually track. I also want to give you my opinion on metrics as I think there is so much confusion about metrics. I believe that a pragmatic approach is reasonable to be practical for each individual situation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We will discuss the following things:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;DevRel North Star metrics: Why they are useful but not sufficient&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Common metrics that are collected in the industry&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;My critique and opinion about this&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_devrel_north_star_metrics&quot;&gt;DevRel North Star Metrics&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Swyx claims nearly all companies settle on one specific metric: &lt;strong&gt;Monthly Active Developers&lt;/strong&gt; (Source: &lt;a href=&quot;https://www.swyx.io/measuring-&quot;&gt;Measuring DevRel by swyx&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Also popular:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Registered Developer Accounts (Source: &lt;a href=&quot;https://dev.to/slashdatahq/developer-marketing-kpis-are-different-from-devrel-kpis-3i8l&quot;&gt;Slashdata Report 2020&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Developer Satisfaction score (Source: &lt;a href=&quot;https://dev.to/slashdatahq/developer-marketing-kpis-are-different-from-devrel-kpis-3i8l&quot;&gt;Slashdata Report 2020&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Time To Hello World (TTHW) (Source: &lt;a href=&quot;https://thefalc.com/2020/12/devrel-metrics-and-why-they-matter/&quot;&gt;Sean Falconers - DevRel Metrics And Why They Matter&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Time to First WOW! Exclamation (TTFWE) (My own invention: The first time a user experiences and realizes the value of your product. Sorry had to sneak that in here 😋)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Number of signups / registrations (Source: &lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations&quot;&gt;Kim Maidas Keystone Framework&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Also, have a look at &lt;a href=&quot;https://devrel-kpis.com/&quot;&gt;DevRel-KPIs.com&lt;/a&gt; for more inspiration.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_common_metrics_in_the_industry&quot;&gt;Common Metrics in the Industry&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So this &lt;em&gt;may&lt;/em&gt; be useful when you have to report one or two numbers to management, but not sufficient of what DevRel is actually doing in their day-to-day work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Many more metrics have been collected and I will just link them here for you to explore and get an idea.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I really like the supporting DevRel Metrics &lt;em&gt;swyx&lt;/em&gt; compiled for his North Star metric &lt;strong&gt;Monthly Active Developers&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/swyx-devrel-metrics.png&quot; alt=&quot;Metrics feeding into Monthly Active Developers. Community: Number of Members, Topics, Contributions, Orbit Level 1, Events, Attendees, Superusers. Content: Newsletter subs, YouTube subs, Twitter follows, Workshops complete, Confs/Hackathons, Meetups, Traffic/ SEO Authority. Product: Launch users, Launch mentions, Prioritized issues, Integration/tooling, Sean Ellis Question, ???. Bad Metrics: GitHub Stars, GA UTM Tag, Badges Scanned, NPS&quot; width=&quot;90%&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. Metrics that feed into Monthly Active Developers North Star Metric.(Source: &lt;a href=&quot;https://www.swyx.io/measuring-&quot;&gt;Measuring DevRel by swyx&lt;/a&gt;)&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;From &lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations&quot;&gt;Kim Maidas Keystone Framework&lt;/a&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations/#ib-toc-anchor-9&quot;&gt;Reach&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations/#ib-toc-anchor-12&quot;&gt;Awareness&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations/#ib-toc-anchor-15&quot;&gt;Engagement&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations/#ib-toc-anchor-18&quot;&gt;DevRel Qualified Leads&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Also again &lt;a href=&quot;https://devrel-kpis.com/&quot;&gt;DevRel-KPIs.com&lt;/a&gt; is a great resource to get you going.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_are_there_bad_metrics&quot;&gt;Are There Bad Metrics&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I would say &lt;strong&gt;It depends&lt;/strong&gt; 😋&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Usually you do not want to be measured with a marketing metric. We are dealing with relations here, remember? But if we produce content for example that is for creating awareness or inspiration. What metrics can we actually collect to measure its success? In my opinion this would be something like views or likes or Github-stars.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I suggest the following: Be pragmatic with what you track. There is no harm in collecting a marketing metric if it fits your current situation. If management cares about these sometimes so called &lt;strong&gt;Vanity Metrics&lt;/strong&gt;, even better. Easy to collect and report on.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But do not get caught up in them! An audience is not a community and you want to foster real relationships 😊&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_my_critique_and_opinion_about_this&quot;&gt;My Critique and Opinion About This&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It always felt wrong as a software developer to reduce a complex topic into a single number. It feels even more so with DevRel. I get that management would like to have a single number to gauge how DevRel is doing. But DevRel performs a cross-functional function in a company. The metrics are influenced by a lot of departments and also ultimately by the state your product is in.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A metric like &lt;strong&gt;Monthly Active Developers&lt;/strong&gt; is a great metric if the management trusts that you influence it positively. The problem is, that it is usually influenced by a lot of departments like product, support, technical writing, marketing and so forth. If your product has sharp edges you can not work around even with the best onboarding and with the best feedback for engineering you can possibly provide: Good luck with improving your TTHW!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The only thing you can then do is to try and improve the supporting metrics as &lt;em&gt;swyx&lt;/em&gt; suggests. But even this will not get you far in my opinion because you are only applying bandaids.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Also tieing your activities to a North Star metric may sometimes be hard as it can lag significantly behind. Not every relationship or piece of content has an impact immediately. Often it is a compounding effect of positive encounters that tips the scale. Relationships are built over time!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_conclusion_part_2&quot;&gt;Conclusion Part 2&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In this post we discussed popular DevRel-North Star metrics like &lt;strong&gt;Monthly Active Developers&lt;/strong&gt; used in the industry. They are useful when reporting to management, but not sufficient to measure the complex day-to-day work or specific project/campaigns DevRel is focusing on in a specific company.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We gave a lot of pointers on what you can also collect with the general recommmendation to be pragmatic and, if possible, to focus on metrics that cover relationships.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the next part of this series we will cover Kim Maidas Keystone Framework. It is a great framework if you are just starting out! I use it with a few extensions. It is useful in my current situation and it includes the &lt;strong&gt;Relations&lt;/strong&gt; part of a DevRel-Practitioner!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Photo by Igor Mashkov: &lt;a href=&quot;https://www.pexels.com/photo/radio-telescope-against-sky-with-stars-6325001/&quot;&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_devrel_north_star_metrics&quot;&gt;DevRel North Star Metrics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_common_metrics_in_the_industry&quot;&gt;Common Metrics in the Industry&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_are_there_bad_metrics&quot;&gt;Are There Bad Metrics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_my_critique_and_opinion_about_this&quot;&gt;My Critique and Opinion About This&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_conclusion_part_2&quot;&gt;Conclusion Part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>A Comprehensive DevRel Metrics Guide (Part 1): Why Track Metrics Anyway?</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-06-01-a-comprehensive-devrel-metrics-guide-part1.html</link>
      <pubDate>Thu, 1 Jun 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-06-01-a-comprehensive-devrel-metrics-guide-part1.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/comprehensive-devrel-metrics-guide-part1-cover.jpg&quot; alt=&quot;comprehensive devrel metrics guide part1 cover&quot; width=&quot;60%&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Metrics are the bane of existence for DevRel folks out there. At least in my perception. There seems to be a state of constant confusion and vague advice. I even watched a panel discussion about metrics once, where everybody seemed to avoid giving exact recommendations on how to tackle them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I embarked on a mission to get this sorted out for myself only to discover, that it is complicated enough to spend hours on end on it :-D&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This post-series brings together everything I found out about DevRel metrics. I surfaced a ton by doing extensive research over 20+ hours and applying it directly at my current company.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;At the end of the series you will have a solid understanding of:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Why you should even track anything?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What should you even track?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How to make a strong case for DevRel with your metrics?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How to do reporting?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_start_from_the_top&quot;&gt;Start From The Top&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The age-old question &lt;strong&gt;Why should I measure?&lt;/strong&gt; and you always get the same Drucker quote… Do not worry: Not here!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For me tracking metrics helps me see clearer in terms of direction. As my manager put it: “You can run pretty fast in the wrong direction! So you better NOT do that!”&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_what_does_your_company_care_about&quot;&gt;What does your Company Care about?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Let us face the harsh truth first: &quot;Nearly all companies care about is money!&quot;. For me this is clear and it should be clear to you. Money keeps the lights on and your paycheck delivered to your bank account. This is not just me who thinks like this but a lot of DevRel folks have written about this already.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Often there is one key metric that is used to communicate the health of a company: The North Star or Keystone.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Also as a side note: Just because your company only really cares about money, it is not the thing you aim for in your job directly as you will see later!&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_what_is_a_north_starkeystone_metric&quot;&gt;What Is a North Star/Keystone Metric?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I stand on the shoulders of giants here as I like the following definitions:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Tera Viago says that a North Star Metric is your company metric. And “In the end it is all about money and customer satisfaction”! (Source: &lt;a href=&quot;https://www.youtube.com/watch?v=KXGXfbQfrrI&amp;amp;ab_channel=DevRel&quot;&gt;YouTube-Video&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sean Falconer defines it as &quot;A North Star metric is a single measurement that is predictive to your company’s or product’s long-term success.&quot; (Source: &lt;a href=&quot;https://thefalc.com/2020/12/devrel-metrics-and-why-they-matter/&quot;&gt;Blog Post&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Examples from companies:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Spotify: Time Spent listening&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;airbnb: Booked nights&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;LinkedIn: Monthly Active Users (MAU)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_what_is_your_company_north_star&quot;&gt;What is your Company North Star?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So how does this translate to metrics for your company? It may be one of those:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Annual recurring revenue (ARR)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Number of Sign Ups&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Number of Paying customers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To everyone I have talked to by now they know their companies North Star as it is communicated often through all channels.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_why_do_i_need_a_company_north_star_for_devrel_metrics&quot;&gt;Why do I need a Company North Star for DevRel Metrics?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you look for metrics to measure you should always strive to find the metrics that are tied directly to company goals in some way.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But there is a catch and something I had to wrap my head around. DevRel is so far away from a hard North Star metric as it could be.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Kurt Kemple has a nice chain-of-metrics graphic which illustrates this dilemma.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/chain-of-trusted-metrics-kurt-kemple.png&quot; alt=&quot;chain of trusted metrics kurt kemple&quot; width=&quot;90%&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. Chain of trusted metrics (Source: &lt;a href=&quot;https://theworst.dev/developer-advocates-guide-to-metrics-and-reporting&quot;&gt;Kurt Kemples Developer Advocates Guide to Metrics and Reporting&lt;/a&gt;). You see that everything DevRel does is at the end of the chain. And the farther away you get from your North Star, the harder it gets to tie them to a hard and trusted metric like Annual Recurring Revenue (ARR).&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_why_should_you_care_about_devrel_metrics&quot;&gt;Why should you care about DevRel-Metrics?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;All this DevRel-Metrics talk makes me tired. Why should I care about metrics, when all I want to do is help my developer community?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Well, there are two things to consider:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;If you can not communicate your value to upper management by showing how you impact &lt;strong&gt;their&lt;/strong&gt; metrics&amp;#8230;&amp;#8203; Your value might be underestimated. And guess who gets laid off more likely? Yes, somebody not helping the company succeed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There are so many different things you can do to improve the life of your development community. Blog posts, tutorials in written or video form, engaging directly by giving talks. Providing great docs. But what should you do? If you do not track what has an impact on your business you just do &lt;strong&gt;not&lt;/strong&gt; know. For example at my current company we are testing a lot of stuff that we &lt;em&gt;think&lt;/em&gt; will help our community and our company. And we measure it as good as we can. Some things turned out useless already. Some others were surprisingly helpful. Without a metric, we would not know what to focus on.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_what_are_we_going_to_do&quot;&gt;What Are We Going to Do?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The thing I realized is that determining what to measure and how to tie it to a meaningful company metric is the reason I struggle to wrap my head around DevRel-Metrics: They ARE hard to make sense of and I have to find the ones that are important for &lt;strong&gt;my&lt;/strong&gt; company!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What adds to that is that they are diverse and also distributed across different areas.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So over the next few blog posts we will look at:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;A lot of metrics suggested by knowledgeable DevRel practitioners and thinkers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then we will discuss &lt;a href=&quot;https://maida.kim/how-to-measure-the-value-of-developer-relations&quot;&gt;Kim Maidas Keystone Framework&lt;/a&gt;. Where she explains what metrics she tracks and how she makes them quantifiable, so they can be communicated in cold hard numbers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After that we will dive into the different development stages companies can be in and what it means for choosing the correct metrics. Because what is important to track for a startup is completely different for an enterprise company.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the last part I will share my own experiences and opinion in applying the Keystone Framework and extending it to my needs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_conclusion_part_1&quot;&gt;Conclusion Part 1&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Tying your metrics to your companies North Star in a meaningful way is important but difficult. DevRel-Metrics are usually far away from cold hard numbers relating to a North Star.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But measuring and communicating your value is important to not get laid off and to get an idea what is actually working.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So in the next part we will look at a plethora of metrics other more influential DevRel practitioners compiled.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Cover art image by Daniel Torobekov: &lt;a href=&quot;https://www.pexels.com/de-de/foto/armaturenbrett-des-auf-dem-flugplatz-geparkten-flugzeugs-5262805&quot;&gt;Source&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_start_from_the_top&quot;&gt;Start From The Top&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_what_does_your_company_care_about&quot;&gt;What does your Company Care about?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_what_is_a_north_starkeystone_metric&quot;&gt;What Is a North Star/Keystone Metric?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_what_is_your_company_north_star&quot;&gt;What is your Company North Star?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_why_do_i_need_a_company_north_star_for_devrel_metrics&quot;&gt;Why do I need a Company North Star for DevRel Metrics?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_why_should_you_care_about_devrel_metrics&quot;&gt;Why should you care about DevRel-Metrics?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_what_are_we_going_to_do&quot;&gt;What Are We Going to Do?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_conclusion_part_1&quot;&gt;Conclusion Part 1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>How to Create Subtitle-Files (srt) with WhisperAI</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-03-20-create-subtitles-with-whisperai.html</link>
      <pubDate>Mon, 20 Mar 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-03-20-create-subtitles-with-whisperai.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/ruby_chen_whisperai.png&quot; alt=&quot;ruby chen whisperai&quot; width=&quot;60%&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For my tutorial videos I want to provide high-quality subtitles. But I did not want to write them myself as this is a tedious task.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Luckily there is &lt;a href=&quot;https://github.com/openai/whisper&quot;&gt;WhisperAI&lt;/a&gt; that can help me, or so it promises 😂 Time to give it a shot for my current project.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_install_whisperai&quot;&gt;Install WhisperAI&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I followed their installation guide on their GitHub-Repository side. It is a Python tool so the first step I did was setting up a virtual-environment (my current installed version is &lt;code&gt;3.9.6&lt;/code&gt; on macOS. Here are all the commands I ran:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;shell&quot;&gt;## I installed python with brew as far as I remember ;-)
## Initialize and activate the virtualenv
python3 -m venv venv
source venv/bin/activate

## Install latest WhisperAI from Github
pip install git+https://github.com/openai/whisper.git

## Install ffmpeg
brew install ffmpeg&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_create_util_script_for_easier_handling&quot;&gt;Create Util-Script for Easier Handling&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With that set I created a little script based on &lt;a href=&quot;https://gist.github.com/yasinuygun/a5aaa24af9f5531872e4c6c863fd793f&quot;&gt;this Gist&lt;/a&gt;. It was for an older version of WhisperAI so I had to implement some changes. Save it as &lt;code&gt;createSrt.py&lt;/code&gt; or whatever name you like 😋:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;import sys

import whisper
from whisper.utils import get_writer


def run(input_path: str, output_name: str = &quot;&quot;, output_directory: str = &quot;./&quot;) -&amp;gt; None:
    model = whisper.load_model(&quot;medium&quot;)
    result = model.transcribe(input_path)

    writer = get_writer(&quot;srt&quot;, str(output_directory))
    writer(result, output_name)

def main() -&amp;gt; None:
    if len(sys.argv) != 4:
        print(
            &quot;Error: Invalid number of arguments.\n&quot;
            &quot;Usage: python createSrt.py &amp;lt;input-path&amp;gt; &amp;lt;output-name&amp;gt; &amp;lt;output-directory&amp;gt;\n&quot;
            &quot;Example: python createSrt.py transcribed.srt ./transcribed&quot;
        )
        sys.exit(1)

    run(input_path=sys.argv[1], output_name=sys.argv[2], output_directory=sys.argv[3])


if __name__ == &quot;__main__&quot;:
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_usage_of_util_script&quot;&gt;Usage of Util-Script&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can call it like this and it can handle &lt;code&gt;.wav&lt;/code&gt; and also &lt;code&gt;.mp4&lt;/code&gt;. So you do not even have to export your videos in another format to use it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;shell&quot;&gt;python createSrt.py &amp;lt;path to your mp4/wav file&amp;gt; &amp;lt;name of the srt file&amp;gt; &amp;lt;path to where to save the srt file&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_adjustments&quot;&gt;Adjustments&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you want to use another model instead of &lt;code&gt;medium&lt;/code&gt; you have to change the following line and replace &lt;code&gt;medium&lt;/code&gt; with a model &lt;a href=&quot;https://github.com/openai/whisper#available-models-and-languages&quot;&gt;documented here&lt;/a&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;shell&quot;&gt;model = whisper.load_model(&quot;medium&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you want to change the output format you can use one of the following instead of &lt;code&gt;srt&lt;/code&gt;: &lt;code&gt;vtt&lt;/code&gt;, &lt;code&gt;tsv&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt;. Change it in the following line:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;shell&quot;&gt;writer = get_writer(&quot;srt&quot;, str(output_directory))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Happy transcribing 🦄&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Let Grails fly in the cloud</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-02-13-Grails-and-fly-io.html</link>
      <pubDate>Mon, 13 Feb 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-02-13-Grails-and-fly-io.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This week I wanted to load test a &lt;a href=&quot;https://grails.org&quot;&gt;grails&lt;/a&gt; application under real conditions.
So I needed a simple way to deploy a grails application to a real server (not my notebook).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock text-center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/grails-fly.dio.png&quot; alt=&quot;grails fly.dio&quot; width=&quot;60%&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So, I asked my followers on twitter and mastodon, what cloud service I should use.&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://mastodontech.de/@rdmueller/109825870006686282/embed&quot; class=&quot;mastodon-embed&quot; style=&quot;max-width: 100%; border: 0&quot; width=&quot;400&quot; allowfullscreen=&quot;allowfullscreen&quot;&gt;&lt;/iframe&gt;&lt;script src=&quot;https://mastodontech.de/embed.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I quickly got a response from &lt;a href=&quot;https://twitter.com/patbaumgartner&quot;&gt;Patrick Baumgartner&lt;/a&gt; to use &lt;a href=&quot;https://fly.io&quot;&gt;fly.io&lt;/a&gt; as a service.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Fly IO has some free tier. See - &lt;a href=&quot;https://t.co/iJP12wPWSe&quot;&gt;https://t.co/iJP12wPWSe&lt;/a&gt;&lt;br&gt;&lt;br&gt;I haven&amp;#39;t used it yet because I run my dockerized apps on my NAS &lt;a href=&quot;https://twitter.com/Synology?ref_src=twsrc%5Etfw&quot;&gt;@Synology&lt;/a&gt;&lt;/p&gt;&amp;mdash; Patrick Baumgartner (@patbaumgartner) &lt;a href=&quot;https://twitter.com/patbaumgartner/status/1623204567029514242?ref_src=twsrc%5Etfw&quot;&gt;February 8, 2023&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A quick check showed me that fly.io seems to be really a simple service with a good free tier.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Let&amp;#8217;s see how you can deploy your grails app to fly.io &amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_setup_a_grails_starter&quot;&gt;Setup a Grails Starter&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;First, go to &lt;a href=&quot;https://start.grails.org/&quot; class=&quot;bare&quot;&gt;https://start.grails.org/&lt;/a&gt; and download a starter app.
Since I didn&amp;#8217;t modify the defaults, a simple&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;curl -O https://start.grails.org/myapp.zip
unzip myapp.zip&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;also does the trick.
You can now create some simple domain objects as described in the quick start guide &quot;https://guides.grails.org/creating-your-first-grails-app/guide/index.html[Creating your first Grails Application]&quot; - but you don&amp;#8217;t have to.
The basic application template will be enough to test the deployment to fly.io .&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now, modify the app to create a fat-jar file instead of a .war .
Remove the reference to the &lt;code&gt;war&lt;/code&gt; plugin from the &lt;code&gt;build.gradle&lt;/code&gt; config (line 19):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;groovy&quot;&gt;//apply plugin:&quot;war&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In order to avoid having to set up a database, I also modified the production configuration to use an in-memory database.
In &lt;code&gt;grails-app/conf/application.yml&lt;/code&gt;, I copied the development datasource over to the production one (line 122):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;title&quot;&gt;grails-app/conf/application.yml&lt;/div&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;production:
    dataSource:
        dbCreate: create-drop
        url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_and_deploy_to_fly_io&quot;&gt;&amp;#8230;&amp;#8203; and deploy to fly.io&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Next, create a simple &lt;code&gt;Dockerfile&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Dockerfile&lt;/div&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;dockerfile&quot;&gt;FROM openjdk:14-ea-alpine3.10

EXPOSE 8080

WORKDIR /app
COPY *.jar application.jar

CMD [&quot;java&quot;,&quot;-Djava.security.egd=file:/dev/./urandom&quot;,&quot;-jar&quot;,&quot;/app/application.jar&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock warning&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;i class=&quot;fa icon-warning&quot; title=&quot;Warning&quot;&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
yes, this is not perfect. It is just a quick hack.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now, everything is prepared for the last few steps.
To test your grails app, execute the following steps on the command line:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;./grailsw package
cp build/libs/myapp-0.1.jar .
docker build --tag=&quot;grails-sample/complete:0.1&quot; .
docker run -p 8080:8080 grails-sample/complete:0.1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This will test-run your app locally as docker image.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To deploy it to fly.io, execute&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code&gt;./grailsw package
cp build/libs/myapp-0.1.jar .
fly launch
fly apps list&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now, this is the part where you have to leave the free tier, but it is still cheap.
If you go to your monitoring dashboard at fly.io, you will notice that your app crashed because of low memory (256MB).
So, scale it up to 1GB (don&amp;#8217;t have to redeploy) and it will run flawless :-)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Hope this little guide will help you with your own deployment.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;for feedback and discussion: &lt;a href=&quot;https://twitter.com/RalfDMueller/status/1625217620508135429&quot;&gt;Twitter&lt;/a&gt;, &lt;a href=&quot;https://mastodontech.de/@rdmueller/109859111382637873&quot;&gt;Mastodon&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_setup_a_grails_starter&quot;&gt;Setup a Grails Starter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_and_deploy_to_fly_io&quot;&gt;&amp;#8230;&amp;#8203; and deploy to fly.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Nerd-Spielzeug: WiFi AP</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2023-01-26-nerd-toy-ap.html</link>
      <pubDate>Thu, 26 Jan 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2023-01-26-nerd-toy-ap.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das letzte Mal habe ich von den Features von Zümi erzählt.
Dieses Mal möchte ich die Umsetzung des ersten Features beschreiben.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Da ich mit dem Aufsetzen des WiFi Access Points die meisten Probleme hatte, beginne ich auch damit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das Ziel ist es den Raspberry so aufzusetzen, dass er einen Access Point bereitstellt, über den man auf einen Webserver und somit webbasierte Software auf dem Raspberry Pi zugreifen kann.
Als Bonus soll sich der Raspberry Pi auch über ein weiteres WiFi Netz mit dem Internet verbinden und diese Verbindung durchreichen.
In diesem Fall spricht man auch von &lt;em&gt;Bridging&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2023/raspi-ap.dio.png&quot; alt=&quot;raspi ap.dio&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Warum ist das so schwierig?
Den Raspberry Pi betreibe ich gerne headless (ohne Monitor) und verbinde mich per SSH über WiFi mit ihm.
Wenn ich nun mit der WiFi-Konfiguration rumspiele und etwas schiefläuft, dann ist die Wahrscheinlichkeit hoch, dass ich von Vorne anfangen muss, weil ich mich ausgesperrt habe 😒.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Eine zweite Herausforderung ist die Tatsache, dass ein WiFi-Modul zwei Verbindungen herstellen muss.
Aber dieses Problem haben schon andere schlaue Köpfe gelöst.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_lösung&quot;&gt;Lösung&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Auf der Suche im Internet nach einer Lösung bin ich auf viele Tutorials gestossen.
So beschreibt z.B. die Raspberry Pi Dokumentation direkt das &lt;a href=&quot;https://www.raspberrypi.com/documentation/computers/configuration.html#setting-up-a-routed-wireless-access-point&quot;&gt;Setup des Wireless Access Points&lt;/a&gt;.
Hier wird die WiFi-Verbindung jedoch auf den Ethernet-Port geroutet.
Auch das manuelle Setup sagt mir nicht ganz zu, da die Erfahrungen mit solchen Tutorials, gepaart mit meinem Know-How, nicht immer positiv waren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Lösung habe ich dann auf &lt;a href=&quot;https://raspap.com/&quot; class=&quot;bare&quot;&gt;https://raspap.com/&lt;/a&gt; gefunden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&quot;The easiest, full-featured wireless router setup for Debian-based devices. Period.&quot;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Eine Open Source WiFi Access Point Lösung mit Web-Interface 😍.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das initiale installieren geht über ein geführtes Setup ganz leicht.
Beim Konfigurieren sperrt man sich aber ganz leicht aus.
Deshalb hier meine Tipps:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;beim Aufsetzen des Raspi, nach dem ersten Booten über &lt;code&gt;sudo raspi-config&lt;/code&gt; das WiFi-Passwort neu setzen.
Aus Sicherheitsgründen wurde es mit einem Token ersetzt, welcher zu Problemen mit dem RaspAP Frontend führt.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;befolge die Anleitung auf &lt;a href=&quot;https://docs.raspap.com/ap-sta/&quot;&gt;AP-STA&lt;/a&gt; peinlich genau&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Beim Start des Setup die erste Frage nach dem Installationsverzeichnis &lt;code&gt;/var/www/html&lt;/code&gt; verneinen, um als Verzeichnis &lt;code&gt;/var/www/html/raspap&lt;/code&gt; anzugeben.
Dadurch ist RaspAP dann unter &lt;a href=&quot;http://server/raspap&quot; class=&quot;bare&quot;&gt;http://server/raspap&lt;/a&gt; erreichbar und der dafür installiere Webserver kann leicht noch für eigene Websites verwendet werden.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Im RaspAP Frontend unter dem Punkt &quot;Wireless Client&quot; die bestehende Verbindung erneut herstellen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Der &quot;WiFi client AP mode&quot;-Button ist weiter ausgegraut?
Unter dem Reiter &quot;Logging&quot; das Logging kurz aktivieren und speichern.
Danach sollte der Button funktionieren.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_lösung&quot;&gt;Lösung&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Docs-as-Code Gedanken</title>
      <link>https://fiveandahalfstars.ninja/blog/2023/2022-01-11-thoughts-on-docs-as-code.html</link>
      <pubDate>Wed, 11 Jan 2023 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2023/2022-01-11-thoughts-on-docs-as-code.html</guid>
      <description>
      &lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;docusaurus und mdx&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Antora syntax&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Antora repositories&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;reicht SSG aus?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!-- toc disabled --&gt;
	  </description>
    </item>
    
    <item>
      <title>Nerd-Spielzeug: Zümi</title>
      <link>https://fiveandahalfstars.ninja/blog/2022/2022-12-20-nerd-toy-zumi.html</link>
      <pubDate>Tue, 20 Dec 2022 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2022/2022-12-20-nerd-toy-zumi.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die letzten Jahre habe ich mich immer wieder für verschiedene nerdige Themen wie 3D-Druck, Raspberry Pi, Arduino und Elektronik interessiert.
Aber ich habe mir nie die Zeit genommen was mit diesem Wissen umzusetzen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Doch jetzt ist es an der Zeit.
Inspiriert von Zümi, einem kleinen Roboter-Auto mit Raspberry Pi unter der Haube, habe ich angefangen mein eigenes Nerd-Spielzeug umzusetzen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Aber fangen wir vorne an.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_was_ist_zümi&quot;&gt;Was ist Zümi?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zümi ist ein cleveres Lernspielzeug der Firma Robolink.
Anscheinend wurde er mittlerweile auf Zumi umgetauft, das hindert mich aber nicht daran, ihn weiterhin Zümi zu nennen, denn ich habe meinen durch &lt;a href=&quot;https://www.kickstarter.com/projects/robolink/driving-into-the-world-of-ai-zumi&quot;&gt;die damalige Kickstarter Kampagne&lt;/a&gt; als &quot;Zümi&quot; bekommen :-).
Den besten Überblick über die Features von Zümi gibt es natürlich auf der &lt;a href=&quot;https://www.robolink.com/products/zumi&quot;&gt;Produktwebsite&lt;/a&gt;.
Lasst mich die Features aber nochmal aus der Sicht eines Nerds beschreiben.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_was_kann_zümi&quot;&gt;Was kann Zümi?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zümi ist &lt;strong&gt;autonom&lt;/strong&gt;. Er verfügt über einen Akku mit Ladelogik, zwei Motoren, ein kleines, monochromes OLED-Display, eine Kamera und einen Raspberry Pi.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Der Raspberry Pi braucht seine Zeit zum Booten und kann sich nicht um die Ladelogik kümmern.
Deshalb wurde er ganz clever um einen &lt;strong&gt;Arduino&lt;/strong&gt; ergänzt, der die Ladelogik übernimmt und das Display ansteuert.
Dadurch kann er beim Laden den Zustand am Display anzeigen und bringt beim Einschalten zwei animierte Augen auf das Display, die anzeigen, dass der Raspberry aufwacht.
So wird die Zeit des Bootvorgangs clever überbrückt.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das eingebaute Display ist sehr klein und eignet sich somit nicht sehr gut für die Programmierung.
Deshalb haben sich die Entwickler ein weiteres cleveres Detail einfallen lassen.
Zümi macht nach dem Booten einen &lt;strong&gt;WiFi-Access-Point&lt;/strong&gt; auf.
Auf dem Display wird der Name des WiFi-Netzwerks angezeigt und Zümi reagiert sogar auf eine Verbindung mit der Ausgabe der URL, über die man nach dem Verbindungsaufbau das Dashboard erreicht.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Über das Dashboard kann Zümi noch in das standard WLAN-Netz integriert werden, so daß eine &lt;strong&gt;WiFi-Bridge&lt;/strong&gt; ins Internet aufgebaut wird.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Über das Dashboard stehen mehrere &lt;strong&gt;Jupyter Notebooks&lt;/strong&gt; mit Tutorials zur Verfügung.
Diese Tutorials zeigen, wie Zümi gesteuert wird.
Highlights sind eine Gesichtserkennung und eine QR-Code-Erkennung.
Beide sind über &lt;strong&gt;openCV&lt;/strong&gt; realisiert.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zur genaueren Steuerung der Motoren verfügt Zümi noch über einen &lt;strong&gt;Beschleunigungs&lt;/strong&gt;- und einen &lt;strong&gt;Gyro-Sensor&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Alles in allem eine sehr runde Geschichte, wäre da nicht der Raspberry Pi Zero der ersten Generation.
Dieser verfügt über nur einen Core und fühlt sich dadurch langsam an.
Das System blockiert öfters und vermittelt das Gefühl, dass es nicht für größere Aufgaben geeignet ist.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das von Robolink bereitgestellte SD-Card-Image ist etwas älter und läuft somit nicht auf einem Pi Zero 2.
Da unklar ist, was und wie alles auf dem Image installiert ist, ist ein Upgrade schwierig.
Robolink selbst scheint kein Interesse an einem Upgrade zu haben.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Somit habe ich mir zum Ziel gesetzt mein eigenes Nerd-Spielzeug in ähnlicher Art und Weise aufzusetzen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In den nächsten Blog-Posts werde ich Schritt für Schritt erklären, wie ich dabei vorgehen. Lasst Euch überraschen!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_was_ist_zümi&quot;&gt;Was ist Zümi?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_was_kann_zümi&quot;&gt;Was kann Zümi?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Nerd-Toy: Zümi</title>
      <link>https://fiveandahalfstars.ninja/blog/2022/2022-12-20-nerd-toy-zumi-en.html</link>
      <pubDate>Tue, 20 Dec 2022 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2022/2022-12-20-nerd-toy-zumi-en.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For the last few years, I&amp;#8217;ve been interested in various nerdy topics like 3D printing, Raspberry Pi, Arduino and electronics.
But I have never taken the time to do anything with this knowledge.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But now it&amp;#8217;s time.
Inspired by Zümi, a small robot car with Raspberry Pi under the bonnet, I have started to implement my own nerd toy.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But let&amp;#8217;s start at the beginning.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_what_is_zümi&quot;&gt;What is Zümi?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/zumi.png&quot; alt=&quot;zumi&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zümi is a clever educational toy from the company Robolink.
Apparently it has been renamed Zumi in the meantime, but that doesn&amp;#8217;t stop me from still calling it Zümi, because I got mine through &lt;a href=&quot;https://www.kickstarter.com/projects/robolink/driving-into-the-world-of-ai-zumi&quot;&gt;the Kickstarter campaign at the time&lt;/a&gt; as &quot;Zümi&quot; :-).
Of course, the best overview of Zümi&amp;#8217;s features can be found on the &lt;a href=&quot;https://www.robolink.com/products/zumi&quot;&gt;product website&lt;/a&gt;.
But let me describe the features again from a nerd&amp;#8217;s point of view.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_what_can_zümi_do&quot;&gt;What can Zümi do?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zümi is &lt;strong&gt;autonomous&lt;/strong&gt;. It has a battery with charging logic, two motors, a small monochrome OLED display, a camera and a Raspberry Pi.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The Raspberry Pi takes its time to boot up and cannot take care of the charging logic.
Therefore, it was cleverly supplemented with an &lt;strong&gt;Arduino&lt;/strong&gt;, which takes over the charging logic and controls the display.
This allows it to show the status on the display when charging and brings two animated eyes on the display when switching on, indicating that the Raspberry is waking up.
This cleverly bridges the time of the boot process.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The built-in display is very small and therefore not very suitable for programming.
Therefore, the developers have come up with another clever detail.
After booting, Zümi opens a &lt;strong&gt;WiFi access point&lt;/strong&gt;.
The name of the WiFi network is shown on the display and Zümi even responds to a connection by outputting the URL that is used to reach the dashboard after the connection is established.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Via the dashboard, Zümi can also be integrated into the standard WLAN network, so that a &lt;strong&gt;WiFi bridge&lt;/strong&gt; to the Internet is established.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Several &lt;strong&gt;Jupyter Notebooks&lt;/strong&gt; with tutorials are available via the dashboard.
These tutorials show how Zümi is controlled.
Highlights are a face recognition and a QR code recognition.
Both are realised via &lt;strong&gt;openCV&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For more precise control of the motors, Zümi also has an &lt;strong&gt;acceleration&lt;/strong&gt; and a &lt;strong&gt;gyro sensor&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;All in all, a very well-rounded story, were it not for the first-generation Raspberry Pi Zero.
This has only one core and feels slow as a result.
The system locks up frequently and gives the feeling that it is not suitable for larger tasks.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The SD card image provided by Robolink is somewhat older and therefore does not run on a Pi Zero 2.
Since it is unclear what and how everything is installed on the image, upgrading is difficult.
Robolink itself seems to have no interest in an upgrade.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I have set myself the goal of setting up my own nerd toy in a similar way.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the next blog posts I will explain step by step how I proceed. Let me surprise you!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_what_is_zümi&quot;&gt;What is Zümi?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_what_can_zümi_do&quot;&gt;What can Zümi do?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Stoizismus - Praktische Philosophie für den IT-Alltag</title>
      <link>https://fiveandahalfstars.ninja/blog/2022/2022-09-04-Stoizismus-praktische-Philosophie-Einstieg.html</link>
      <pubDate>Sun, 4 Sep 2022 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2022/2022-09-04-Stoizismus-praktische-Philosophie-Einstieg.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Dieser Post basiert auf meinem Vortrag &lt;strong&gt;Stoizismus - Eine Praktische Philosophie für den IT-Alltag&lt;/strong&gt;.
Das Video dazu ist auf &lt;a href=&quot;https://fiveandahalfstars.ninja/talks/johannesdienst_talks.html&quot;&gt;meiner Talkseite&lt;/a&gt; verlinkt.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_philosophie_für_it&quot;&gt;Philosophie für IT?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Warum Philosophie auf einem Tech-Blog? Mag sich die Eine oder der Andere Fragen. Für mich ist der Umgang mit Menschen manchmal schwierig,
da ich eine eher kurze &lt;em&gt;Zündschnur&lt;/em&gt; besitze. Technik ist einfach und logisch im Vergleich zum Verhalten von so manchen Kolleg:innen.
Gerade in der heutigen Arbeitswelt lässt sich Kommunikation nicht mehr vermeiden. Also musste ich für mich einen Weg finden, professionell
mit Herausforderungen in diesem Bereich umzugehen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ich weiß nicht mehr wo es war, aber so um 2018 bin ich über den Stoizismus gestolpert und habe mich seitdem immer weiter damit beschäftigt.
Inzwischen bin ich der festen Überzeugung, dass diese Philosophie für jede:n ein Gewinn ist, der:die sich auch nur damit auseinandersetzt.
Deswegen erzähle ich jedem davon, der es nicht hören will ;-)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_stoizismus_praktische_philosophie&quot;&gt;Stoizismus - Praktische Philosophie&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Philosophie hat in vielen Köpfen etwas mit weltfremden Diskussionen zu tun, die keinen praktischen Nutzen haben im Alltag.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im Gegensatz dazu stehen die &lt;strong&gt;Praktischen Philosophien&lt;/strong&gt;, zu denen auch der &lt;em&gt;Stoizismus&lt;/em&gt; gehört. Sie beschäftigen sich explizit mit dem Alltag, genauer gesagt mit zwischenmenschlichen Beziehungen. Stoizismus im Speziellen stellt sich die folgende Frage:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Wie lebe ich mein Leben so, dass ich überglücklich bin und es reibungslos verläuft?&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In der stoischen Philosophie geht es darum ein Leben in Einklang mit den stoischen Tugenden zu leben und der:die &lt;strong&gt;perfekte&lt;/strong&gt; Stoiker:in zu werden, der:die unter anderem sein:ihr Urteilsvermögen ungetrübt von Emotionen einsetzen kann. Da wir Menschen sind und Emotionen zu unserer Natur gehören ist dieses Ideal natürlich nicht erreichbar. Dazu aber später mehr.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Aus diesem Streben erwächst dann das Glück!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Gehen wir zum nächsten Abschnitt, in dem ich die Kernaussagen des Stoizismus zusammenfasse.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Hier bitte nicht vergessen, dass ich ein Schüler des Stoizismus bin und es zusätzlich viele verschiedene Interpretierungen in der Literatur gibt!&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_kernideen&quot;&gt;Kernideen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Eine wunderschöne grafische Zusammenfassung der stoischen Kernideen ist das stoische Glücksdreieck. Weit oben steht &lt;em&gt;Verantwortung zu übernehmen&lt;/em&gt; für sein Tun und seine Reaktionen. Das ist aber erst möglich, wenn die beiden Fundamente &lt;em&gt;Leben in Aretè&lt;/em&gt; und &lt;em&gt;Fokus auf das Kontrollierbare&lt;/em&gt; gemeistert wurden.
In der Mitte steht das höchste Ziel: &lt;em&gt;Eudaimonia&lt;/em&gt;. Ein zusammengesetztes Wort mit der Bedeutung, mit seinem inneren Selbst (&lt;em&gt;Daimon&lt;/em&gt;) im Reinen zu sein (&lt;em&gt;Eu&lt;/em&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/stoicism_happiness_triangle_de.drawio.png&quot; alt=&quot;Stoisches Glückdreieck aus dem Buch &amp;quot;The Little Book of Stoicism&amp;quot; von Jonas Salzgeber&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_leben_in_areté&quot;&gt;Leben in Areté&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In dieser Ecke des Dreiecks geht es um Tugenden und darum nach diesen zu leben. Das bedeutet in unserem Handeln diese Tugenden auszudrücken.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Weißheit&lt;/strong&gt;: Im Sinne von guter Urteilsfähigkeit, die überlegt ist und nicht gedankenlos&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Gerechtigkeit&lt;/strong&gt;: Hier geht es um die Beziehung zu unseren Mitmenschen, in denen integer und fair gehandelt werden soll&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mut&lt;/strong&gt;: In einer Situation richtig zu handeln. Entgegen jedweden Widerstands (auch inneren)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Selbst-Disziplin&lt;/strong&gt;: Im Stoizismus vor allem die angemessene Reaktion auf Emotionen und starkes Begehren in jeder Hinsicht&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Noch hinzuzufügen ist, dass für Stoiker:innen alle Tugenden wichtig sind. Wird eine nicht gelebt, dann wird es schwierig Eudaimonia zu erreichen.
Trotzdem haben alle Stoiker:innen in ihrem Leben festgestellt, dass sie Probleme haben immer nach den Tugenden zu handeln.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Seneca ist ein sehr berühmtes Beispiel. Als einer der reichsten Männer seiner Zeit wurde ihm oft Heuchlerei vorgeworfen, da er im Überfluss lebte. Er pflegte ein abendliches Journal in dem er offen über alle Vorkommnisse das Tages schrieb. Er war sich seinen Fehlern bewusst. Wichtig ist nur, sein Bestes zu geben!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_fokus_auf_das_kontrollierbare&quot;&gt;Fokus auf das Kontrollierbare&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Umgangsprachlich wird der Begriff &lt;em&gt;stoisch&lt;/em&gt; mit Gefühlslosigkeit gleichgesetzt. Das kommt daher, dass Stoiker:innen ihren Fokus auf das Kontrollierbare legen.
Dazu unterteilen sie Dinge, die Passieren, in vier Kategorien:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Kein Einfluss&lt;/strong&gt;: Fast alle externen Einflüsse&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Teilweiser Einfluss&lt;/strong&gt;: Zum Beispiel die Reaktionen auf unser Verhalten oder auch Gesundheit&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Indifferent aber bevorzugt&lt;/strong&gt;: Reich oder arm zu sein sollte keinen Einfluss darauf haben, ob wir ein stoisches Leben führen. Reich sein ist aber definitiv angenehmer ;-)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hoher Einfluss&lt;/strong&gt;: Die wichtigste Kategorie, aber auch die kleinste. Unser Urteilsvermögen und Handeln&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nur die vierte Kategorie können wir wirklich kontrollieren. Das heißt, sich zum Beispiel über das Wetter zu beschweren ist nicht sinnvoll,
da es nur akzeptiert werden kann. Die Kunst ist es, in jeder Situation in Einklang mit den stoischen Tugenden zu reagieren.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_verantwortung_übernehmen&quot;&gt;Verantwortung übernehmen&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ohne die beiden Fundamente kann keine Verantwortung übernommen werden. Was &lt;em&gt;wirklich&lt;/em&gt; in unserer Verantwortung liegt ist, &lt;em&gt;wie&lt;/em&gt; wir auf ein Ereignis reagieren.
So ist es dem Wetter (um bei dem Beispiel zu bleiben) ziemlich egal, ob wir uns darüber freuen, indifferent oder genervt sind. Es liegt also in unserer
Verantwortung zu entscheiden, wie wir uns fühlen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das ist einfach geschrieben, aber sehr schwierig umzusetzen! Deswegen sehen wir uns in den nächsten Abschnitten an, welchen praktischen Nutzen
uns das bringt und welche stoischen Übungen es gibt, mit denen wir das stoische Glücksdreieck verinnerlichen können.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_praktischer_nutzen&quot;&gt;Praktischer Nutzen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Für mich der größte praktische Nutzen war die Erkenntnis, dass wir einen hohen Einfluss auf unsere Reaktionen auf externe Ereignisse haben.
Insbesondere in den normalen Reaktionen in Social Media sehen wir genau das Gegenteil. Hier ist die &lt;strong&gt;Empörungskultur&lt;/strong&gt; am Werk. Auf jeden Tweet wird sofort scharf in den Kommentaren reagiert, bis hin zu Beleidigungen. Sehr oft unberechtigt, aber auch ohne die Einsicht, dass das Medium an sich sehr beschränkt ist in seiner Ausdrucksfähigkeit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/stimulus_reaction_simple_de.drawio.png&quot; alt=&quot;Auf einen Stimulus wird normalerweise ohne nachzudenken instinktiv reagiert.&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. Auf einen Stimulus wird normalerweise ohne nachzudenken instinktiv reagiert.&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Stattdessen können wir uns einen Effekt zunutze machen, der uns wieder die Kontrolle zurückgibt. Es gibt eine kurze Zeitspanne zwischen dem Ereignis und unserer spontanen Reaktion darauf. Mir persönlich ist er erst aufgefallen, nachdem ich davon gewusst habe. Ich rate daher dazu, sich selbst genauer zu beobachten.
Die Chancen stehen sehr gut, dass es bei allen Menschen so ist ;-). Greifen wir genau zu diesem Zeitpunkt ein, können wir rational überlegen, was die passende Reaktion auf ein Ereignis ist. Dadurch gewinnen wir die Kontrolle zurück und lösen uns davon, nur emotionsgesteuert zu handeln.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/stimulus_reaction_stoic_de.drawio.png&quot; alt=&quot;Die stoische Vorgehensweise auf einen Stimulus zuerst zurückzutreten und überlegt zu reagieren.&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 2. Die stoische Vorgehensweise auf einen Stimulus zuerst zurückzutreten und überlegt zu reagieren.&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_stoische_übungen&quot;&gt;Stoische Übungen&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Um in jeder Situation angemessen zu reagieren, ist es nicht genug über das theoretische Wissen zu verfügen. Das wussten schon die antiken Stoiker:innen.
Deswegen gibt es eine große Palette an stoischen Übungen, die uns mental trainieren, angemessen zu reagieren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ich werde zwei meiner Lieblingsübungen vorstellen, da sie mir persönlich sehr geholfen haben im Alltag.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_gelassenheit_kaufen&quot;&gt;Gelassenheit kaufen&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Beim Essen habe ich das Talent zu kleckern. Diese Übung hat mir geholfen, die negative Stimme in meinem Kopf nach einem solchen Vorfall auszuschalten und stattdessen zu üben, mit Unfällen umzugehen. Bis dahin habe ich nach jeder Kleckerei eine Weile darüber sinniert, wie dumm das doch war. Inzwischen kann ich über das meiste Lachen
oder es ist mir einfach egal. Deswegen kaufe ich mir mit dieser Übung Gelassenheit. Sie geht so:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sobald ein kleines Missgeschick geschieht: Die Gelegenheit nutzen und sich selbst beobachten. Die Gefühle akzeptieren und dann zu sich selbst sagen während des
Aufräumens: &quot;Für diese Kleinigkeit kaufe ich mir Gelassenheit!&quot; Die Effekte bei mir waren eine größere Gelassenheit im Alltag. Kleine Missgeschicke hängen mir
inzwischen gar nicht mehr nach, was mich zufriedener mit mir selbst gemacht hat.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_premeditatio_malorum&quot;&gt;Premeditatio Malorum&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Kennt ihr diese Menschen, die alles exakt bis auf die letzte Minute durchplanen, wenn sie auf Reisen gehen. Nur um dann festzustellen, dass sie etwas Wichtiges wie
Zahnpasta vergessen haben? Genau so jemand war ich auch. Jetzt liegt es aber in der Natur der Sache, bei einer Reise irgendetwas zu vergessen. Das Meiste ist aber
ersetzbar. Drogerieartikel gibt es überall und auch größere Dinge wie Netzteile für Elektronik.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Übung &lt;em&gt;Premeditatio Malorum&lt;/em&gt; hilft bei der mentalen Vorbereitung auf Fehlschläge. Es macht einen großen Unterschied, ob über mögliche Schwierigkeiten nachgedacht wurde
oder nicht. Dadurch kann in der Situation rationaler reagiert werden, selbst wenn sie im Kopf noch nicht durchgespielt wurde. Alleine der Akt darüber nachzudenken hilft. Deswegen rate ich dazu, nicht vollständig alles zu durchdenken, sondern nur ein paar Eventualitäten.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Inzwischen bin ich bei Reisen dadurch sehr entspannt, sogar als ich dann wirklich einmal meine Zahnbürste und Zahnpasta vergessen hatte.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_weiterführende_gedanken_und_leseempfehlungen&quot;&gt;Weiterführende Gedanken und Leseempfehlungen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Es gibt noch viel mehr zu entdecken im Stoizismus als das, was ich hier beschrieben habe. Jedes mal, wenn ich wieder ein Buch über Stoizismus in die Hand nehme und es lese, kommen
neue Einsichten dazu. Ich kann nur empfehlen mit dem einsteigerfreundlichen Buch &lt;em&gt;The Little Book of Stoicism&lt;/em&gt; von Jonas Salzgeber loszulegen, da es sehr
konzentriert alle wichtigen Kernaussagen des Stoizismus verständlich rüberbringt.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_leseempfehlungen&quot;&gt;Leseempfehlungen&lt;/h3&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Little Book of Stoicism - Jonas Salzgeber&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Practicing Stoic - Farnsworth&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How to Think Like a Roman Emperor - Donald Robertson&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.njlifehacks.com/&quot;&gt;Webseite von Nils und Jonas Salzgeber&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_philosophie_für_it&quot;&gt;Philosophie für IT?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_stoizismus_praktische_philosophie&quot;&gt;Stoizismus - Praktische Philosophie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_kernideen&quot;&gt;Kernideen&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_leben_in_areté&quot;&gt;Leben in Areté&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_fokus_auf_das_kontrollierbare&quot;&gt;Fokus auf das Kontrollierbare&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_verantwortung_übernehmen&quot;&gt;Verantwortung übernehmen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_praktischer_nutzen&quot;&gt;Praktischer Nutzen&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_stoische_übungen&quot;&gt;Stoische Übungen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_gelassenheit_kaufen&quot;&gt;Gelassenheit kaufen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_premeditatio_malorum&quot;&gt;Premeditatio Malorum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_weiterführende_gedanken_und_leseempfehlungen&quot;&gt;Weiterführende Gedanken und Leseempfehlungen&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_leseempfehlungen&quot;&gt;Leseempfehlungen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Stoicism - Practical Philosophy for Your Daily IT-Life</title>
      <link>https://fiveandahalfstars.ninja/blog/2022/2022-09-04-Stoizismus-praktische-Philosophie-Einstieg-en.html</link>
      <pubDate>Sun, 4 Sep 2022 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2022/2022-09-04-Stoizismus-praktische-Philosophie-Einstieg-en.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;This post is based on my talk &lt;strong&gt;Stoicism - A Practical Philosophy for Everyday IT&lt;/strong&gt;.
The video for this is linked on &lt;a href=&quot;https://fiveandahalfstars.ninja/talks/johannesdienst_talks.html&quot;&gt;my talk page&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_philosophy_for_it&quot;&gt;Philosophy for IT?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Why philosophy on a tech blog? One or the other may ask. For me, dealing with people is sometimes difficult,
because I have a rather short &lt;em&gt;fuse&lt;/em&gt;. Technology is simple and logical compared to the behavior of some colleagues.
Especially in today&amp;#8217;s working world, communication cannot be avoided. So I had to find a way for myself to deal professionally with challenges in this area.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I don&amp;#8217;t remember where it was, but around 2018 I stumbled across Stoicism and have been studying it ever since.
In the meantime, I am firmly convinced that this philosophy is an asset for anyone who even explores it.
That&amp;#8217;s why I tell everyone about it, who doesn&amp;#8217;t want to hear it ;-)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_stoicism_practical_philosophy&quot;&gt;Stoicism - Practical Philosophy&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Philosophy has in many minds something to do with unworldly discussions that have no practical use in everyday life.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In contrast to this are the &lt;strong&gt;practical philosophies&lt;/strong&gt;, to which also the &lt;em&gt;Stoicism&lt;/em&gt; belongs. They deal explicitly with everyday life, or more precisely with interpersonal relationships. Stoicism in particular poses the following question:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;How do I live my life so that I am overjoyed and it runs smoothly?&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Stoic philosophy is about living a life in accordance with the Stoic virtues and becoming the &lt;strong&gt;perfect&lt;/strong&gt; Stoic who can, among other things, use his or her judgment unclouded by emotion. Since we are human beings and emotions are part of our nature, this ideal is of course not attainable. But more about that later.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;From this striving then happiness arises!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Let&amp;#8217;s go to the next section, where I summarize the core statements of Stoicism.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Here please do not forget that I am a student of Stoicism and that there are additionally many different interpretations in the literature!&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_core_ideas&quot;&gt;Core Ideas&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A beautiful graphic summary of the core Stoic ideas is the Stoic triangle of happiness. High up is &lt;em&gt;taking responsibility&lt;/em&gt; for one&amp;#8217;s actions and reactions. But this is only possible when the two foundations &lt;em&gt;Living in Aretè&lt;/em&gt; and &lt;em&gt;Focusing on the Controllable&lt;/em&gt; have been mastered.
In the middle is the highest goal: &lt;em&gt;Eudaimonia&lt;/em&gt;. A compound word with the meaning of being at peace (&lt;em&gt;Eu&lt;/em&gt;) with one&amp;#8217;s inner self (&lt;em&gt;Daimon&lt;/em&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/stoicism_happiness_triangle_en.drawio.png&quot; alt=&quot;Stoic triangle of happiness from the book &amp;quot;The Little Book of Stoicism&amp;quot; by Jonas Salzgeber&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_life_in_areté&quot;&gt;Life in Areté&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This corner of the triangle is about virtues and living by them. This means expressing these virtues in our actions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wisdom&lt;/strong&gt;: In the sense of good judgment that is deliberate and not thoughtless.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Justice&lt;/strong&gt;: This is about our relationship with our fellow human beings in which we should act with integrity and fairness&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Courage&lt;/strong&gt;: To act rightly in a situation. Against any resistance (even internal).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Self-discipline&lt;/strong&gt;: In Stoicism, especially the appropriate response to emotions and strong desire in any respect.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It should be added that for Stoics all virtues are important. If one is not lived, then it becomes difficult to achieve eudaimonia.
Nevertheless, all Stoics have found in their lives that they have problems to always act according to the virtues.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Seneca is a very famous example. As one of the richest men of his time, he was often accused of hypocrisy because he lived in abundance. He used to keep an evening journal in which he openly wrote about all the events of the day. He was aware of his mistakes. The important thing is to do your best!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_focus_on_the_controllable&quot;&gt;Focus on the Controllable&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Colloquially, the term &lt;em&gt;stoic&lt;/em&gt; is equated with insensitivity. This is because stoics focus on the controllable.
For this purpose, they divide things that happen into four categories:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No influence&lt;/strong&gt;: Almost all external influences&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Partial influence&lt;/strong&gt;: For example, reactions to our behavior or even health .&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Indifferent but preferred&lt;/strong&gt;: Being rich or poor should have no influence on whether we live a stoic life. But being rich is definitely more pleasant ;-)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;High Influence&lt;/strong&gt;: The most important category, but also the smallest. Our judgment and actions&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Only the fourth category we can really control. That is, complaining about the weather, for example, is not useful,
since it can only be accepted. The art is to react in any situation in accordance with the stoic virtues.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_assume_responsibility&quot;&gt;Assume Responsibility&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Without the two foundations, no responsibility can be taken. What &lt;em&gt;really&lt;/em&gt; is our responsibility is &lt;em&gt;how&lt;/em&gt; we react to an event.
Thus, the weather (to stay with the example) doesn&amp;#8217;t really care whether we are happy about it, indifferent, or annoyed. So it is our
responsibility to decide how we feel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s easy to write, but very difficult to implement! That&amp;#8217;s why in the next sections we&amp;#8217;ll look at the practical benefits of this and what stoic exercises are available to help us internalize the stoic happiness triangle.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_practical_benefit&quot;&gt;Practical benefit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For me, the biggest practical benefit was the realization that we have a high impact on our reactions to external events.
In particular, we see just the opposite in normal reactions on social media. This is where the &lt;strong&gt;empathy culture&lt;/strong&gt; is at work. Every tweet is immediately reacted to sharply in the comments, up to and including insults. Very often unjustified, but also without the insight that the medium itself is very limited in its ability to express itself.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/stimulus_reaction_simple_en.drawio.png&quot; alt=&quot;A stimulus is usually responded to instinctively without thinking.&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. A stimulus is usually responded to instinctively without thinking.&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Instead, we can take advantage of an effect that puts us back in control. There is a short period of time between the event and our spontaneous reaction to it. Personally, I only noticed it after I knew about it. So my advice is to observe yourself more closely.
Chances are very good that it is like that for all people ;-). If we intervene at that exact moment, we can rationally consider what is the appropriate reaction to an event. In this way, we regain control and free ourselves from acting only emotionally.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/stimulus_reaction_stoic_en.drawio.png&quot; alt=&quot;The stoic approach to a stimulus of first stepping back and responding thoughtfully.&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 2. The stoic approach to a stimulus of first stepping back and responding thoughtfully.&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_stoic_exercises&quot;&gt;Stoic Exercises&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To react appropriately in any situation, it is not enough to have the theoretical knowledge. This was already known to the ancient Stoics.
That is why there is a wide range of stoic exercises that train us mentally to react appropriately.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I will present two of my favorite exercises, as they have helped me personally in everyday life.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_buy_serenity&quot;&gt;Buy Serenity&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When it comes to eating, I have a talent for spilling. This exercise has helped me turn off the negative voice in my head after such an incident and instead practice dealing with accidents. Until then, after every spill, I would ponder for a while how stupid it was. In the meantime I can laugh about most of it
or I just don&amp;#8217;t care. That&amp;#8217;s why I buy myself serenity with this exercise. It goes like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As soon as a little mishap happens: Take the opportunity to observe yourself. Accept the feelings and then say to yourself during the
Clean up: &quot;For this little thing, I buy serenity!&quot; The effects for me have been greater serenity in everyday life. Small mishaps are no longer
which has made me more satisfied with myself.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_premeditatio_malorum&quot;&gt;Premeditatio Malorum&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You know those people who plan everything exactly down to the last minute when they go on a trip? Only to realize that they have forgotten something important like
toothpaste? I was exactly that kind of person. Now, it is in the nature of things to forget something when traveling. But most things are
replaceable. Drugstore items are everywhere and so are larger items like power supplies for electronics.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &lt;em&gt;Premeditatio Malorum&lt;/em&gt; exercise helps with mental preparation for failure. It makes a big difference whether possible difficulties have been thought about
or not. This allows for a more rational reaction in the situation, even if it has not yet been played out in the mind. Just the act of thinking about it helps. That&amp;#8217;s why I advise not to think through everything completely, but only a few contingencies.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the meantime, I am very relaxed when traveling, even when I really forgot my toothbrush and toothpaste.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_further_thoughts_and_reading_recommendations&quot;&gt;Further Thoughts and Reading Recommendations&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There is much more to discover in Stoicism than what I have described here. Every time I pick up a book on Stoicism and read it, I gain new insights. I can only recommend to start with the beginner-friendly book &lt;em&gt;The Little Book of Stoicism&lt;/em&gt; by Jonas Salzgeber, it contains
all important core statements of Stoicism in a very concentrated and understandable way.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_reading_recommendations&quot;&gt;Reading Recommendations&lt;/h3&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Little Book of Stoicism - Jonas Salzgeber&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Practicing Stoic - Farnsworth&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How to Think Like a Roman Emperor - Donald Robertson&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.njlifehacks.com/&quot;&gt;Website of Nils and Jonas Salzgeber&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_philosophy_for_it&quot;&gt;Philosophy for IT?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_stoicism_practical_philosophy&quot;&gt;Stoicism - Practical Philosophy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_core_ideas&quot;&gt;Core Ideas&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_life_in_areté&quot;&gt;Life in Areté&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_focus_on_the_controllable&quot;&gt;Focus on the Controllable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_assume_responsibility&quot;&gt;Assume Responsibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_practical_benefit&quot;&gt;Practical benefit&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_stoic_exercises&quot;&gt;Stoic Exercises&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_buy_serenity&quot;&gt;Buy Serenity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_premeditatio_malorum&quot;&gt;Premeditatio Malorum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_further_thoughts_and_reading_recommendations&quot;&gt;Further Thoughts and Reading Recommendations&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_reading_recommendations&quot;&gt;Reading Recommendations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Architecture Decision Records Teil 3 - Im Kontext von arc42</title>
      <link>https://fiveandahalfstars.ninja/blog/2022/2022-08-29-ADRs-und-arc42.html</link>
      <pubDate>Mon, 29 Aug 2022 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2022/2022-08-29-ADRs-und-arc42.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nachdem ich im &lt;a href=&quot;https://fiveandahalfstars.ninja/blog/2021/2021-11-02-adrs-das-format&quot;&gt;letzten Artikel&lt;/a&gt; das &lt;em&gt;Was&lt;/em&gt; und &lt;em&gt;Wie&lt;/em&gt; von Architecture Decision Records erläutert habe, geht es diesmal darum Architekturentscheidungen in den Kontext des &lt;a href=&quot;&quot;&gt;arc42-Templates&lt;/a&gt; einzubetten.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_arc42_von_oben_nach_unten_auszufüllen&quot;&gt;arc42 - Von oben nach unten auszufüllen?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Gliederung von arc42 sieht auf den ersten Blick angenehm und logisch aus (aus &lt;a href=&quot;https://www.arc42.de/overview&quot;&gt;arc42&lt;/a&gt;):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1 Einführung und Ziele&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 Randbedingungen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3 Kontextabgrenzung&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4 Lösungsstrategie&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;5 Bausteinsicht&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;6 Laufzeitsicht&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;7 Verteilungssicht&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;8 Querschnittliche Konzepte&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;9 Entwurfsentscheidungen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10 Qualitätsanforderungen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;11 Risiken und technische Schulden&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;12 Glossar&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das liegt daran, dass diese Struktur für &lt;strong&gt;Lesende&lt;/strong&gt; ist!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lesende interessiert nicht, welche Qualitätsanforderungen an ein System gestellt wurden und wie diese zur vorhandenen Softwarearchitektur geführt haben. Für sie ist nur das Ergebnis wichtig. Außer es gibt Probleme mit dieser Lösung, dazu aber später mehr.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_wie_erstelle_ich_die_dokumentation_als_schreibender&quot;&gt;Wie erstelle ich die Dokumentation als Schreibende*r&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wird die Architekturdokumentation gerade erstellt, sollte anders vorgegangen werden. Ralf und ich haben dazu im weiter unten verlinkten Talk die folgende Bearbeitungsreihenfolge für die Kapitel vorgeschlagen:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;1 &amp;#8594; 2 &amp;#8594; 3 &amp;#8594; &lt;strong&gt;10&lt;/strong&gt; &amp;#8594; 9 &amp;#8594; &amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Kapitel 1-3 sind notwendig, um festzulegen &lt;em&gt;WAS&lt;/em&gt; gebaut werden soll, &lt;em&gt;WELCHE&lt;/em&gt; Randbedingen nicht änderbar sind und in &lt;em&gt;WELCHEM&lt;/em&gt; Kontext das zu bauende System operiert. Im Grund genommen ist es der Vertrag, der mit Kunden geschlossen wird.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bevor nun die Architektur entworfen werden kann, ist es sinnvoll die Qualitätsanforderungen abzuklären. Das Ergebnis sollte ein gewichteter Qualitätsattributbaum sein, der die maximal &lt;strong&gt;fünf&lt;/strong&gt; höchstpriorisierten Qualitätsattribute enthält. Die folgende Abbildung zeigt einen Ausschnitt eines solchen Baumes für ein System, das ich betreut habe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/qualityattributetree_example.drawio.png&quot; alt=&quot;Gewichteter Qualitätsattributbaum mit den Qualitätsattributen Usability und Sicherheit und den Prioritäten hinter den Attributen.&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Für das System dieses Qualitätsattributsbaumes waren die Qualitätsattribute sehr klar, dank zweier Fachexpert*innen, die sich in ihrem Bereich und mit dem abzulösenden Altsystem sehr gut auskannten. In den meisten Fällen wird es eher darauf hinauslaufen mit unklaren Qualitätsanfordungen wie &quot;Das System mus performant sein!&quot; konfrontiert zu werden. Oder es werden mehrere sich widersprechende Qualitätsattribute gefordert. Hier hilft es Vergleiche mit anderen Systemen heranzuziehen. Im Falle von Performanz kann von Kundenseite zum Beispiel ein System benannt werden, dass als performant empfunden wird.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_entscheidungen_treffen_im_hinblick_auf_qualitätsanforderungen&quot;&gt;Entscheidungen treffen im Hinblick auf Qualitätsanforderungen&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Erst jetzt kann ich daran gehen die Architektur zu entwerfen und die Entwurfsentscheidungen als ADRs zu dokumentieren. Es empfiehlt sich am Ende eines jeden ADRs eine weitere Überschrift einzufügen in der die, von der Entscheidung betroffenen, Qualitätsattribute aus Kapitel 10 verlinkt werden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
Hin und wieder kommt es vor, dass eine Entscheidung auf kein Qualitätsattribut &lt;em&gt;einzahlt&lt;/em&gt;. Hier ist zu überprüfen, ob sie architekturrelevant ist und in arc42 dokumentiert werden sollte. Eventuell ist es auch eine Randbedingung.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_warum_qualitätsattribute_und_entwurfsentscheidungen_in_so_späten_kapiteln&quot;&gt;Warum Qualitätsattribute und Entwurfsentscheidungen in so späten Kapiteln?&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lesende interessieren sich normalerweise nicht dafür auf welcher Grundlage ein System gebaut wurde. Viel interessanter ist doch zu sehen &lt;strong&gt;WIE&lt;/strong&gt; es aufgebaut ist. Architekturdiagramme wie die Microservicearchitektur von Netflix zum Beispiel wirken imposant und eindrucksvoll. Die Kompromisse im Betrieb und die Komplexität im Entwicklungs- und Deploymentprozess treten in den Hintergrund.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Für Softwarearchitekturschaffende oder falls es Probleme gibt sind Kapitel neun und zehn aber hochinteressant. Denn dort steht im besten Fall nachvollziehbar &lt;strong&gt;WARUM&lt;/strong&gt; ein System so gebaut ist und welche Entwurfsentscheidungen dazu geführt haben, dass ein gewisses Problem aufgetreten ist. Nicht selten sind unklare Qualitätsanforderungen die wahre Ursache für Schwächen des Systems!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_wie_geht_es_weiter&quot;&gt;Wie geht es weiter?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In diesem Blog habe ich beschrieben, welche Bedeutung Architekturentscheidungen im Kontext von arc42 einnehmen und wie die Bearbeitungsreihenfolge bei der Erstellung eines Systems aussehen sollte.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im nächsten Post gehen wir &lt;em&gt;endlich&lt;/em&gt; auf die Technik ein, mit der Architekturentscheidungen effizient gesammelt und verwaltet werden können.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wer lieber ein Video zu arc42 und Architekturentscheidungen angucken will dem empfehle ich schamlos meinen Vortrag mit Ralf:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;880&quot; height=&quot;540&quot; src=&quot;https://www.youtube.com/embed/1RUgt73tXoE&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_arc42_von_oben_nach_unten_auszufüllen&quot;&gt;arc42 - Von oben nach unten auszufüllen?&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_wie_erstelle_ich_die_dokumentation_als_schreibender&quot;&gt;Wie erstelle ich die Dokumentation als Schreibende*r&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_entscheidungen_treffen_im_hinblick_auf_qualitätsanforderungen&quot;&gt;Entscheidungen treffen im Hinblick auf Qualitätsanforderungen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_warum_qualitätsattribute_und_entwurfsentscheidungen_in_so_späten_kapiteln&quot;&gt;Warum Qualitätsattribute und Entwurfsentscheidungen in so späten Kapiteln?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_wie_geht_es_weiter&quot;&gt;Wie geht es weiter?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>JavaLand 2022 Gedächtnistörtchen</title>
      <link>https://fiveandahalfstars.ninja/blog/2022/2022-03-20-JavaLand-Cake.html</link>
      <pubDate>Sun, 20 Mar 2022 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2022/2022-03-20-JavaLand-Cake.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im JavaLand gab es diesmal super leckere Törtchen - wohl auch Petit Fours genannt.
Ich dachte erst, die würden viel zu süß sein, aber nein.
Nach anfänglich einem einzelnen, konnte ich mich auf drei plus Espresso steigern.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/JavaLand22/petitfours.jpg&quot; alt=&quot;petitfours&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Diese kleinen Biester waren so lecker, dass ich, kaum war ich daheim angekommen, versuchen musste sie mit meinen limitierten Backkünsten nachzumachen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Hier mein Rezept&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_zutaten&quot;&gt;Zutaten&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_biskuitboden&quot;&gt;biskuitboden&lt;/h3&gt;
&lt;div class=&quot;ulist checklist&quot;&gt;
&lt;ul class=&quot;checklist&quot;&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 200g Zucker&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 5 Eier&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 150g Mehl&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 50g Speisestärke&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 1/2 Pck. Backpulver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 1 Pck. Vanillezucker&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_füllung_und_schoko_raspeln&quot;&gt;Füllung und Schoko-Raspeln&lt;/h3&gt;
&lt;div class=&quot;ulist checklist&quot;&gt;
&lt;ul class=&quot;checklist&quot;&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 200g sehr weiche Butter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 300g Milch&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; &lt;a href=&quot;https://www.oetker.de/unsere-produkte/backzutaten/tortencremes/vanilla&quot;&gt;Dr. Oetker TortenCreme Vanilla&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_glasur&quot;&gt;Glasur&lt;/h3&gt;
&lt;div class=&quot;ulist checklist&quot;&gt;
&lt;ul class=&quot;checklist&quot;&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 250g Puderzucker&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 1 Zitrone&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_umhüllung&quot;&gt;Umhüllung&lt;/h3&gt;
&lt;div class=&quot;ulist checklist&quot;&gt;
&lt;ul class=&quot;checklist&quot;&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 1 geheime Zutat&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_rezept&quot;&gt;Rezept&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_biskuitboden_2&quot;&gt;Biskuitboden&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Den Biskuitboden kannst Du auch fertig gebacken und geschnitten kaufen.
Ich habe ihn mal wieder selbst gebacken.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mit dem Thermomix&amp;#8482; ist er auch ganz schnell selbst gemacht.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Backofen auf 180°C vorheizen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Den Boden einer Springform (Ø 26 cm) mit Backpapier auslegen.
Du kannst das Backpapier einfach über den Boden legen und mit dem Rahmen der Springform einspannen.
Das überstehende Backpapier am Besten nicht abschneiden.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rühraufsatz (Schmetterling) in den Thermomix&amp;#8482; einsetzen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;5 Eier in den Mixtopf aufschlagen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 Minuten bei 37°C auf Stufe 4 verrühren&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;200g Zucker und 1 Pkg. Vanillezucker zugeben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10 Minuten bei Stufe 4 weiter aufschlagen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;150g Mehl, 1/2 Pck. Backpulver, 50g Kakaopulver und 50g Speisestärke rechts und links neben den Rühraufsatz (Schmetterling) zugeben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4-8 Sekunden auf Stufe 3 unterheben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rühraufsatz(Schmetterling) entfernen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mit dem Spatel das Mehl noch etwas mehr unterheben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Biskuitteig in die vorbereitete Form geben und 20-25 Minuten bei 180°C backen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Biskuitteig mindestens 10 Minuten abkühlen lassen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;waagerecht mit vier Schnitten in fünf Böden schneiden&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zum Schneiden der Torte habe ich den Tortenschneider aus dem &lt;a href=&quot;https://www.ikea.com/de/de/p/smaksam-tortengarnier-set-10257033/&quot;&gt;Ikea-Set SMAKSAM&lt;/a&gt; genutzt :-).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_tortencreme&quot;&gt;Tortencreme&lt;/h3&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Rühraufsatz (Schmetterling) in den Thermomix&amp;#8482; einsetzen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dr. Oetker TortenCreme Vanilla in den Mixtopf geben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;200g sehr weiche Butter und 300g Milch nach Angabe auf der Dr. Oetker Packung zugeben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mixer langsam von Stufe 1 bis Stufe 5 anstellen und ca. 3 Minuten aufschlagen.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_zusammenbau&quot;&gt;Zusammenbau&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Verteile die TortenCreme auf den Bisquitböden, so dass ein entsprechender Stapel aus Schichten entsteht.
Die TortenCreme muss dabei nicht ganz die Ränder erreichen, denn nach dem Zusammenbau wird aus der runden Torte ein Quadrat herausgeschnitten.
In diesem Bereich sollte die Creme also gut verteilt sein.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vor dem Schneiden aber erstmal die Schichttorte für 2 Stunden in den Kühlschrank geben, damit die TortenCreme fest wird.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nun aus der Schichttorte ein großes Quadrat rausschneiden.
Der Rest ist &quot;Abfall&quot; und kann jetzt vernascht werden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Vor Dir liegt nun ein Quadrat aus leckeren Creme- und Biskuit-Schichten.
Dieses unterteilst Du nun mit 6 Schnitten in 16 kleinere Quadrate.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Löse die Quadrate vorsichtig vom Backpapier und setze sie auf z.B. ein Backblech (sollte in Deinen Kühlschrank passen)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/JavaLand22/Schritt3.jpg&quot; alt=&quot;Schritt3&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_die_glasur&quot;&gt;Die Glasur&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nun gibst Du den Puderzucker in ein Schälchen und rührst mit ein wenig Zitronensaft die Glasur an.
Achtung - nicht zu viel Zitronensaft, damit die Glasur nicht zerfliesst.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Jetzt kommt der Spritzbeutel aus dem &lt;a href=&quot;https://www.ikea.com/de/de/p/smaksam-tortengarnier-set-10257033/&quot;&gt;Ikea-Set SMAKSAM&lt;/a&gt; zum Einsatz.
Mit der breiten Tülle wird der Zuckerguss in drei breiten Strichen aufgetragen und eventuell noch mit irgendwas dekoriert.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Schnell wieder in den Kühlschrank, damit der Zuckerguss fest wird.
30 Minuten sollten hier reichen.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_umhüllung_2&quot;&gt;Umhüllung&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Hier kommt die geheime Zutat zum Einsatz. Leider kenne ich sie nicht.
Ich habe anfang auf Marzipan getippt.
Das lässt sich aber nicht so dünn verarbeiten und ist recht dunkel.
Also habe ich es nochmal mit Fondant probiert - kommt dem Original leider auch nicht so nah.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dennoch, hier ist, was ich gemacht habe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Weisses Fondant möglichst dünn (ca. 1mm) als breiten Streifen (ca 9-12cm) ausrollen.&lt;br&gt;
Die obere und rechte Kannte mit einem Messer gerade schneiden.&lt;br&gt;
Törtchen rechts anlegen, 3x nach links drehen und die rechte und untere Kannte mit einem Messer schneiden.&lt;br&gt;
Anschliessend das Törtchen mit dem so abgemessenen Fondant ummanteln.&lt;br&gt;
15x wiederholen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wieder nach Belieben jedes Törtchen verzieren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;../../images/blog/2022/JavaLand22/marzipan.jpg&quot; alt=&quot;marzipan&quot; width=&quot;45%&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;../../images/blog/2022/JavaLand22/fondant.jpg&quot; alt=&quot;fondant&quot; width=&quot;45%&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Guten Appetit!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;PS: Für Hinweise, wie man das Rezept verbessern kann (vor allem die Ummantelung) bin ich sehr dankbar.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;PS PS: an Stelle der TortenCreme kann man natürlich auch richtige Buttercreme verwenden, so wie sie in &lt;a href=&quot;/blog/2021/2021-02-21-schwarzwaelder-kirsch&quot;&gt;meinem anderen Rezept&lt;/a&gt; beschrieben ist.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2022/JavaLand22/fertig.jpg&quot; alt=&quot;fertig&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_zutaten&quot;&gt;Zutaten&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_biskuitboden&quot;&gt;biskuitboden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_füllung_und_schoko_raspeln&quot;&gt;Füllung und Schoko-Raspeln&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_glasur&quot;&gt;Glasur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_umhüllung&quot;&gt;Umhüllung&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_rezept&quot;&gt;Rezept&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_biskuitboden_2&quot;&gt;Biskuitboden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_tortencreme&quot;&gt;Tortencreme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_zusammenbau&quot;&gt;Zusammenbau&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_die_glasur&quot;&gt;Die Glasur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_umhüllung_2&quot;&gt;Umhüllung&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Remote Dev Environments</title>
      <link>https://fiveandahalfstars.ninja/blog/2021/2021-11-22-Conatinerdevelopment.html</link>
      <pubDate>Mon, 22 Nov 2021 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2021/2021-11-22-Conatinerdevelopment.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Do you remember the times when the biggest challenge to compile a project was to set up the correct build environment with all required dependencies?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The flexibility you have as a developer with current technologies is amazing.
Not only that you can setup your dev environment with docker but you also chose where to run it.
You can even choose to run your IDE on a remote machine.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Let&amp;#8217;s take a look at the options you have with Visual Studio Code or short VS Code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Let&amp;#8217;s start with the standard way you use &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VS Code&lt;/a&gt; for development.
You download and install it.
Then you run it locally, clone your project from a git repository and develop locally.
You have to ensure that everybody who uses the code has all needed external dependencies like build tools installed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2021/vscode.dio.png&quot; alt=&quot;vscode.dio&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s ok, but let&amp;#8217;s take a look how we can help others to get the right start with the right environment for your code.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_move_your_environment_to_a_container&quot;&gt;Move your environment to a container&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The next logical step is to move your environment to a container.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The VS Code team started soon to experiment with splitting up the IDE into a frontend and a server backend.
When you start VS Code on a Windows environment from within the Windows Subsystem for Linux (WSL), it starts the backend server in WSL and then connects to the frontend which runs natively on Windows.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers&quot;&gt;Remote Containers&lt;/a&gt; plugin, you can use this mechanism to start a container with your well defined environment, get the server part of VS Code installed there and connect from the frontend to it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Put a &lt;a href=&quot;https://code.visualstudio.com/docs/remote/create-dev-container#:~:text=In%20this%20document%2C%20we%27ll%20go%20through%20the%20steps,multiple%20containers%20through%20Docker%20Compose.%20More%20items&amp;#8230;&amp;#8203;%20&quot;&gt;&lt;code&gt;devcontainer.json&lt;/code&gt;&lt;/a&gt; in your repository and VS Code will use this container definition as your dev environment.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2021/devcontainer.dio.png&quot; alt=&quot;devcontainer.dio&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_move_your_environment_to_a_remote_machine&quot;&gt;Move your environment to a remote machine&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now that your development environment runs independent of your local VS Code instance, you can even move it to a remote machine.
Maybe one with more power.
And it is easier than you think - with &lt;a href=&quot;https://gitpod.io&quot;&gt;gitpod.io&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Gitpod is basically a free and open source IDE for GitHub.
Choose any github repository and prefix the URL with &lt;code&gt;gitpod.io#&lt;/code&gt;.
This will invoke gitpod which clones the selected repository to a remote container, and asks you if you want to connect the remote container to your local VS Code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2021/remotecontainer.dio.png&quot; alt=&quot;remotecontainer.dio&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_move_your_ide_to_a_remote_machine&quot;&gt;Move your IDE to a remote machine&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you&amp;#8217;ve followed me and gave Gitpod a try, you will have noticed that it not only starts your repository in a remote container.
It also starts an instance of VS Code as web based application!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As a result, you have a full-blown remote development environment which even works with low bandwidth connections.
Only some keystrokes and characters go over the wire.
Your code is always executed on a performant remote machine.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With a &lt;a href=&quot;https://github.com/docToolchain/aoc-2021/blob/main/.gitpod&quot;&gt;&lt;code&gt;.gitpod&lt;/code&gt;&lt;/a&gt; file in your repository, you can even define the container to which the repository is cloned.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock center&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2011/gitpod.dio.png&quot; alt=&quot;gitpod.dio&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I hope this article gave you some new ideas on how to set up your next dev environment.
Have fun coding!&lt;/p&gt;
&lt;/div&gt;
&lt;style&gt;
.center {
  text-align: center;
}
&lt;/style&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Architecture Decision Records Teil 2 - Das strukturierte Format für Architekturentscheidungen</title>
      <link>https://fiveandahalfstars.ninja/blog/2021/2021-11-02-ADRs-Das-Format.html</link>
      <pubDate>Tue, 2 Nov 2021 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2021/2021-11-02-ADRs-Das-Format.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nachdem ich im &lt;a href=&quot;https://fiveandahalfstars.ninja/blog/2021/2021-04-05-adrs-warum&quot;&gt;letzten Artikel&lt;/a&gt; hergeleitet habe, &lt;em&gt;warum&lt;/em&gt; es eine gute Idee ist Entscheidungen
zu dokumentieren, will ich heute das &lt;em&gt;Was&lt;/em&gt; und das &lt;em&gt;Wie&lt;/em&gt; beschreiben.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_was_sollte_ich_dokumentieren&quot;&gt;Was sollte ich dokumentieren?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Basierend auf meinen Erfahrungen lohnt es sich zwei Dinge zu dokumentieren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zum Ersten finde ich es wichtig in einem Team Klarheit über die Technologientscheidungen zu haben.
Wir sind alle Individuen mit bestimmten Vorlieben.
In meinem jetzigen Team haben wir ein buntes Gemisch aus Technologiepräferenzen.
Um unbewusste Ablehnung von implementierten Lösungen durch andere Teammitglieder zu vermeiden und um Klarheit über den Entscheidungsvorgang zu bekommen, dokumentieren wir diese Entscheidungen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Außerdem dokumentieren wir alle Architekturentscheidungen. Aber was ist das eigentlich genau?
Dafür lohnt sich eine Definition, denn Softwarearchitektur selbst ist schon ein schwieriger Begriff.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Architekturentscheidungen wirken sich direkt auf die Softwarearchitektur aus und sind später nur schwer oder gar nicht mehr änderbar.
Sie definieren das Softwaresystem maßgeblich und zahlen im besten Fall direkt auf die Qualitätsanforderungen ein.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Architekturentscheidungen sind immer ein Kompromiss aus verschiedenen Qualitätsanforderungen. Letztere sollten priorisiert vorliegen, so dass
die Entscheidungen immer zugunsten der höher Priorisierten getroffen wird. Das ist wichtig, da es oft zum Konflikt zweier Qualitätsanforderungen kommt.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dazu ein kleines Beispiel: Das Softwaresystem soll als Priorität 1 hohe Security bereitstellen. Außerdem soll es für den Benutzer leicht zu
bedienen sein als Priorität 2. Es steht die Entscheidung an, wie die Benutzerauthentifizierung passieren soll. Hohe Sicherheit bietet die
Zwei-Faktor-Authentifizierung, die aber dummerweise für den Benutzer etwas umständlicher ist als die Kombination Benutzername und Passwort.
Hier schlägt Priorität 1 die Priorität 2 und es wird die Zwei-Faktor-Authentifizierung implementiert!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_wie_dokumentiere_ich_entscheidungen&quot;&gt;Wie dokumentiere ich Entscheidungen?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Für mich müssen die folgenden Anfordungen an die Dokumentation einer Entscheidung erfüllt sein:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Schnell zu erstellen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Leicht zu lesen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Chronologisch nachzuvollziehen&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_entering_architecture_decision_records_adr&quot;&gt;Entering Architecture Decision Records (ADR)&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein hervorragendes Format hat Michael Nygard &lt;a href=&quot;https://www.cognitect.com/blog/2011/11/15/documenting-architecture-decisions&quot;&gt;in einem Blogpost beschrieben&lt;/a&gt;:
Die Architecture Decision Records.
Er schlägt vor, Entscheidungen nach einem festen Schema in einzelnen Dateien abzulegen. In seinem Team ist das als Dateien in einem Repository im Markdown-Format.
Für ihn funktioniert das sehr gut in agil arbeitenden Teams. Sein Format sieht wie folgt aus:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Title&lt;/strong&gt;: Durchnummeriert in der Form ADR-XXX: Nomenphrase&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;: Alle Fakten, die auf diese Entscheidung Einfluss haben. Politisch, sozial, technlogisch etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Decision&lt;/strong&gt;: Die Entscheidung in einem bis maximal zwei Sätzen in aktiver Sprache&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Status&lt;/strong&gt;: Offen, Beschlossen, Ersetzt oder zurückgenommen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consequences&lt;/strong&gt;: Alles was aus der Entscheidung folgt. Positiv wie negativ&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dieses Format kann in einer Datei in einem git-Repository oder als Wikiseite mit Ausfüllhinweisen als sogenanntes ADR-Template abgelegt werden.
Bei Bedarf wird es kopiert und muss &lt;em&gt;nur&lt;/em&gt; ausgefüllt werden. Der Aufwand wird somit stark reduziert.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_für_mein_team_angepasstes_adr_format&quot;&gt;Für mein Team angepasstes ADR-Format&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In meinem Team setzen wir ein leicht angepasstes Format ein.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Title&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Decision&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Status&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Context&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consequences&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alternatives&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wir empfinden es als wichtig, die Entscheidung sowie den Status prominent zu platzieren. Sie sind normalerweise das Wichtigste und Interessanteste für den Leser.
Außerdem haben wir noch den letzten Punkt &lt;em&gt;Alternatives&lt;/em&gt; hinzugefügt, da er bei technologischen Entscheidungen hilft, die Alternativen in der Diskussion näher zu
beleuchten. Wird eine Entscheidung zurückgenommen oder ersetzt stellte dieser Punkt schon ein paar Mal den Ausgangspunkt für weitere Evaluationen dar.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_weitere_formate&quot;&gt;Weitere Formate&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Es gibt noch zahlreiche andere Varianten von ADR-Templates. Auch welche, die sich weniger technologisch orientieren. Ein guter Einstiegspunkt
dafür bietet die &lt;a href=&quot;https://adr.github.io/#existing-adr-templates&quot;&gt;ADR Organization auf Github&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_wie_geht_es_weiter&quot;&gt;Wie geht es weiter?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In diesem Blog habe ich beschrieben, wie Entscheidungen strukturiert mit dem ADR-Template dokumentiert werden können.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im nächsten Post gehen wir auf das arc42 Architekturdokumentationstemplate ein und sehen uns an, wie wir dort die Architecture Decision Records einsetzen.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_was_sollte_ich_dokumentieren&quot;&gt;Was sollte ich dokumentieren?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_wie_dokumentiere_ich_entscheidungen&quot;&gt;Wie dokumentiere ich Entscheidungen?&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_entering_architecture_decision_records_adr&quot;&gt;Entering Architecture Decision Records (ADR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_für_mein_team_angepasstes_adr_format&quot;&gt;Für mein Team angepasstes ADR-Format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_weitere_formate&quot;&gt;Weitere Formate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_wie_geht_es_weiter&quot;&gt;Wie geht es weiter?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Architecture Decision Records Teil 1 - Warum Entscheidungen dokumentieren?</title>
      <link>https://fiveandahalfstars.ninja/blog/2021/2021-04-05-ADRs-Warum.html</link>
      <pubDate>Sun, 11 Apr 2021 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2021/2021-04-05-ADRs-Warum.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Entscheidungen zu dokumentieren stellt meiner Erfahrung nach Verbindlichkeit und Transparenz her.
Um Architekturentscheidungen zu dokumentieren hat sich für mich ein Format namens &lt;em&gt;Architecture Decision Record&lt;/em&gt; (kurz ADR) bewährt.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im Rahmen dieser Artikelserie betten wir die Architecture Decision Records in den größeren Rahmen der Architekturarbeit ein.
Dabei gehe ich insbesondere auf den Kontext des Dokumentationstemplates arc42 und dessen Einsatz im DevOps-Umfeld ein.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wir sehen uns dazu auch intensiver die Technik an, mit der dokumentiert wird. Hier kommen AsciiDoc, Microsites und Git zum Einsatz.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Aber starten wir zuerst mit dem &lt;em&gt;Warum&lt;/em&gt;. Warum ist es eine gute Idee, Entscheidungen zu dokumentieren?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_undokumentierte_entscheidungen_ein_problem_auf_unterschiedlichen_ebenen&quot;&gt;Undokumentierte Entscheidungen - Ein Problem auf unterschiedlichen Ebenen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Undokumentierte Entscheidungen sind oft die Regel. Meistens bleiben sie eine lange Zeit unbemerkt oder kommen nie wieder zur Sprache.
Interessant wird es, wenn an einer Stelle die Frage gestellt wird: &lt;strong&gt;Warum&lt;/strong&gt; ist das &lt;strong&gt;so&lt;/strong&gt;?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dabei ist dieses Problem nicht nur auf technische Dinge beschränkt. Auch zwischenmenschliche Aspekte der Zusammenarbeit sind betroffen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_technische_entscheidungen&quot;&gt;Technische Entscheidungen&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Technik kann alles Mögliche umfassen. Ich nehme mal das Beispiel einer Frameworkentscheidung für einen Microservice heraus.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Inzwischen gibt es zu jeder Programmiersprache unzählige Frameworks, um einen Microservice zu implementieren. Interessanterweise gibt es in einem Team
normalerweise mehrere Meinungen, welches Framework das Beste ist. Deswegen sollte so eine Entscheidung dokumentiert werden. Wichtig hierbei aus meiner Sicht: Die
untersuchten Alternativen mitdokumentieren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In unserem Team hatten wir genau diese Entscheidung zur Wiedervorlage. Wir waren mit unserer alten Implementierung unzufrieden und haben uns einige Alternativen
angesehen und sie mit Performance-Tests und Proof-Of-Concepts evaluiert. Die folgende Entscheidung beruhte auf der erstellten Datenbasis. Alle Alternativen
sind in der Entscheidungsdokumentation zu finden und für jeden nachvollziehbar.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_zwischenmenschliches&quot;&gt;Zwischenmenschliches&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zwischenmenschliches klingt meistens banal, hat aber im Alltag große Auswirkungen auf Arbeitsmoral und Motivation.
Dazu ein Beispiel:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In meinem Team fehlt anscheinend eine Regel, wie mit temporärer Abwesenheit ohne Krankmeldung umgegangen wird. Ein Teamkollege von mir war nur zum Daily
anwesend, aber dann den ganzen Tag nicht mehr in der Teamkommunikation zu sehen. Am Ende des Tages war ich besorgt und leicht ärgerlich zugleich.
Mir war nicht klar, wie er den Tag verbracht hat oder ob etwas passiert ist.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Aus meiner Sicht brauchen wir dafür im Team eine dokumentierte Entscheidung, wie wir mit solchen Abwesenheiten umgehen.
Ziel ist nicht Kollegen:innen zu gängeln, wenn sie sich nicht daran halten. Aber ich kann dann so darauf hinweisen: &quot;Sieh mal, so hatten wir das entschieden,
warum machst Du das nicht so?&quot;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_architekturentscheidungen&quot;&gt;Architekturentscheidungen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Eine besondere Rolle nehmen Entscheidungen ein, die sich auf die Softwarearchitektur eines Softwaresystems beziehen. Meine Definition dieser Entscheidungen ist
die Folgende: &quot;Eine Architekturentscheidung ist im Nachhinein potentiell teuer bis gar nicht zu ändern und bezieht sich auf die Qualitätsanforderungen eines Systems&quot;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Aus meiner Erfahrung sind Architekturentscheidungen dann gefährlich wenn sie &lt;em&gt;unbewusst&lt;/em&gt; getroffen werden. Unbewusst werden sie getroffen, wenn ein System &lt;em&gt;einfach so&lt;/em&gt;
entsteht. Es wird an allen Stellen gearbeitet, aber nie darüber geredet, was mit dem System erreicht werden soll. Sehr oft kommt später die Frage auf:
&quot;Warum ist das so gemacht worden?&quot;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In unserem Team wurde explizit die horizontale Skalierbarkeit als Qualitätsanforderung gesetzt und daraufhin ein Kollege mit der Umsetzung einer API beauftragt.
Am Ende kam eine hochperformante Implementierung heraus, die leider für den Rest des Teams unwartbar war. Hier wurde die Qualitätsanforderung &lt;em&gt;Wartbarkeit&lt;/em&gt; missachtet.
Das hätte durch Transparenz in der Entscheidungsfindung vermieden werden können.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_das_besondere_an_devops_teams&quot;&gt;Das Besondere an DevOps-Teams&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Entscheidungen zu dokumentieren und vor allem zu &lt;em&gt;vergemeinschaften&lt;/em&gt; ist in einem DevOps-Team sehr wichtig. Um als Team effektiv
zu agieren sollte der Kommunikationsaufwand innerhalb des Teams klein gehalten werden. Aus meiner Sicht ist die Maximalgröße von sieben Menschen
schon fast zu groß, da die Kommunikationskanäle im Team sehr viele sind (siehe dazu &lt;a href=&quot;https://www.digitales-denken.de/toolbox/2017/11/28/kommunikationsbeziehungen&quot;&gt;Kommunikationsbeziehungen&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Um mit dieser kleinen Anzahl an Menschen den gesamten Entwicklungszyklus von der Anforderungserhebung beim Kunden bis zum Betrieb des Systems abzudecken
ist effektive Kommunikation unabdingbar. Besonderes Augenmerk ist hier aus meiner Erfahrung heraus auf &lt;strong&gt;Einigkeit&lt;/strong&gt; bei architektonischen und technischen
Entscheidungen zu legen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nichts wirkt sich destruktiver auf das Team aus, als eine im Stillen nicht mitgetragene Entscheidung!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_wie_geht_es_weiter&quot;&gt;Wie geht es weiter?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Inzwischen sollte klar geworden sein, warum ich es wichtig finde Entscheidungen zu dokumentieren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Doch wie geht das eigentlich effektiv und effizient?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im nächsten Post sehen wir uns ein Format namens Architecture Decision Records an. Das eignet sich speziell für Architekturentscheidungen, kann aber auch
auf andere Entscheidungen adaptiert werden.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_undokumentierte_entscheidungen_ein_problem_auf_unterschiedlichen_ebenen&quot;&gt;Undokumentierte Entscheidungen - Ein Problem auf unterschiedlichen Ebenen&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_technische_entscheidungen&quot;&gt;Technische Entscheidungen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_zwischenmenschliches&quot;&gt;Zwischenmenschliches&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_architekturentscheidungen&quot;&gt;Architekturentscheidungen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_das_besondere_an_devops_teams&quot;&gt;Das Besondere an DevOps-Teams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_wie_geht_es_weiter&quot;&gt;Wie geht es weiter?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Schwarzwälder Kirschtorte</title>
      <link>https://fiveandahalfstars.ninja/blog/2021/2021-02-21-Schwarzwaelder-Kirsch.html</link>
      <pubDate>Sun, 21 Feb 2021 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2021/2021-02-21-Schwarzwaelder-Kirsch.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Jedesmal, wenn ich zu Besuch bei meiner Großmutter war, konnte ich wählen, welche Torte es Sonntags geben sollte.
Zur Auswahl standen Schwarzwälder Kirsch und Prinzregenten.
Meist wurde es die Schwarzwälder Kirsch.
Das Originalrezept ist leider nicht überliefert, es war aber natürlich bei weitem Besser als alles, was ich an Schwarzwälder Kirsch sonst vorgesetzt bekommen habe.
Das lag zum einen an der leckeren Buttercreme (nein, Sahne geht gar nicht!) zum anderen aber auch an den leckeren handgeraspelten Schoko-Raspeln.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Letzten Monat habe ich mir die Zeit genommen und versucht das Rezept interativ wieder herzustellen.
Ich habe also Rezepte verglichen, gebacken, probiert und wieder von Vorne angefangen.
Das Ergebnis findest Du nun hier als Rezept für den Thermomix&amp;#8482;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Fotos Deiner Umsetzung bitte gerne auf Twitter mit dem Hashtag #OmasSchwarzwaelderKirsch teilen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2021/02/torte.jpg&quot; alt=&quot;torte&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_zutaten&quot;&gt;Zutaten&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_tortenboden&quot;&gt;Tortenboden&lt;/h3&gt;
&lt;div class=&quot;ulist checklist&quot;&gt;
&lt;ul class=&quot;checklist&quot;&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 200g Zucker&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 5 Eier&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 150g Mehl&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 50g Kakaopulver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 50g Speisestärke&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 1/2 Pck. Backpulver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 1 Pck. Vanillezucker&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_füllung_und_schoko_raspeln&quot;&gt;Füllung und Schoko-Raspeln&lt;/h3&gt;
&lt;div class=&quot;ulist checklist&quot;&gt;
&lt;ul class=&quot;checklist&quot;&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 600 g Milch&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 120 g Zucker&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 2 Pck. Vanillepuddingpulver&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 1 Prise Salz&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 330 g Butter, Zimmertemperatur, in Stücken&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 1 Glas Sauerkirschen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#10063; 200g Blockschokolade&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_rezept&quot;&gt;Rezept&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Anfangs habe ich den Fehler gemacht mit dem Tortenboden anzufangen.
Dadurch ergeben sich zu lange Wartezeiten und das Backen dauert fast einen Tag.
Deshalb fangen wir nun mit der Buttercreme an.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_pudding_für_die_buttercreme&quot;&gt;Pudding (für die Buttercreme)&lt;/h3&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Butter aus dem Kühlschrank nehmen, damit sie Zimmertemperatur annehmen kann.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;600g Milch, 120g Zucker, 2 Pck. Vanillepuddingpulver und eine Prise Salz in den Mixtopf geben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10 Sekunden auf Stufe 4 verrühren&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;7 Minuten bei 100°C auf Stufe 2,5 aufkochen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;in eine große Schüssel umfüllen, und ein Stück hitzebeständige Frischhaltefolie direkt auf den Pudding legen, damit dieser keine Haut bilden kann&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;den Pudding ca. 2 Stunden auf Zimmertemperatur abkühlen lassen&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_dunkler_wiener_boden&quot;&gt;Dunkler Wiener Boden&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Den Wiener Boden kannst Du auch fertig gebacken und geschnitten kaufen - dann ist er aber nur halb so gut.
Mit dem Thermomix&amp;#8482; ist er auch ganz schnell selbst gemacht.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Backofen auf 180°C vorheizen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Den Boden einer Springform (Ø 26 cm) mit Backpapier auslegen.
Du kannst das Backpapier einfach über den Boden legen und mit dem Rahmen der Springform einspannen.
Das überstehende Backpapier am Besten nicht abschneiden.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rühraufsatz (Schmetterling) in den Thermomix&amp;#8482; einsetzen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;5 Eier in den Mixtopf aufschlagen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2 Minuten bei 37°C auf Stufe 4 verrühren&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;200g Zucker und 1 Pkg. Vanillezucker zugeben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10 Minuten bei Stufe 4 weiter aufschlagen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;150g Mehl, 1/2 Pck. Backpulver, 50g Kakaopulver und 50g Speisestärke rechts und links neben den Rühraufsatz (Schmetterling) zugeben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4-8 Sekunden auf Stufe 3 unterheben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rühraufsatz(Schmetterling) entfernen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mit dem Spatel das Mehl noch etwas mehr unterheben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Biskuitteig in die vorbereitete Form geben und 20-25 Minuten bei 180°C backen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Biskuitteig mindestens 10 Minuten abkühlen lassen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;waagerecht mit zwei Schnitten in drei Böden schneiden&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_schokoraspeln&quot;&gt;Schokoraspeln&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wartezeiten kannst Du prima mit dem Raspeln der Schokolade füllen.
Lege dazu die Blockschokolade auf ein Schneidebrett, nimm ein großes scharfes Messer und schneide ganz dünne Raspeln ab, bis die kompletten 200g Blockschokolade geraspelt sind.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_kirschen&quot;&gt;Kirschen&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Auch die Kirschen kannst Du als Pausenfüller schon mal abtropfen lassen.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_buttercreme&quot;&gt;Buttercreme&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wenn nun der Pudding abgekühlt ist (Butter und Pudding müssen ca. Zimmertemperatur haben), mit der Buttercreme fortfahren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;330g Butter in Stücken in den Mixtopf geben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1 Minunte auf Stufe 4 aufschlagen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;nun den Thermomix&amp;#8482; auf 2,5 Minuten bei Stufe 2,5 einstellen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;nach und nach den Pudding auf das laufende Messer zugeben&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10 Sekunden bei Stufe 6 die Creme glatt rühren&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_zusammenbau_der_torte&quot;&gt;Zusammenbau der Torte&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mit einem Tortenretter legst Du nun den untersten Boden auf zwei Stück Backpapier, die sich in der Mitte ca. 2 Zentimeter überlappen.
Mit diesem Trick kannst Du das Backpapier zum Schluss leichter unter der Torte rausziehen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Du solltest jetzt ca. 1050g Buttercreme im Thermomix haben.
Bei der lezten Zubereitung habe ich die Buttercreme nach Gefühl aufgeteilt, ich denke aber, wir sollten die eingebaute Waage nutzen um es uns zu erleichtern.
Die Zahlen sind also momentan Schätzungen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;verteile 300g Buttercreme auf den ersten Boden. Lücken zum Rand hin können später noch leicht verfüllt werden.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;lege 12 ausgewählte Kirschen für die Dekoration beiseite&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;verteile die restlichen abgetropften Kirschen auf der Buttercreme&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;setze den zweiten Boden auf den ersten&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;verteile wieder 300g Buttercreme auf dem Boden&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;setze den dritten Boden auf den zweiten&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;fülle eine &lt;a href=&quot;https://www.amazon.de/Dr-Oetker-Einhand-Garnierspritze-T%C3%BCllen-K%C3%BCchenhelfer/dp/B07CBZDB48/ref=sr_1_9?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;amp;dchild=1&amp;amp;keywords=garnierspritze&amp;amp;qid=1613941035&amp;amp;sr=8-9&quot;&gt;Granierspritze&lt;/a&gt; etwa zur Hälfte mit Buttercreme&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;verteile die restliche Buttercreme auf der Torte und über die Seiten.
Dabei schliesst Du eventuelle Lücken am Rand der Tortenböden.
Keine Angst, das muss nicht super aussehen - die Schokoraspeln werden einiges Kaschieren.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;verteile nun auf der Torte Schokoraspeln, bis die Oberfläche vollständig bedeckt ist&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;nimm nun ein breites Messer und &quot;streiche&quot; jeweils einige Schokoraspeln von unten nach oben über die Ränder der Torte, bis auch der Rand mit Raspeln bedeckt ist.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;zum Schluss setzt Du noch 12 Tupfer Buttercreme mit der Garnierspritze auf den Rand der Torte und verzierst sie mit jeweils einer Kirsche.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;stelle die Torte in den Kühlschrank&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nach ca. zwei Stunden im Kühlschrank ist die Buttercreme fest und die Torte somit servierfertig.
Richtiggute schmeckt sie allerdings, wenn sie ein bis zwei Tage durchgezogen ist.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Guten Appetit!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2021/02/tortenstueck.jpg&quot; alt=&quot;tortenstueck&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_zutaten&quot;&gt;Zutaten&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_tortenboden&quot;&gt;Tortenboden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_füllung_und_schoko_raspeln&quot;&gt;Füllung und Schoko-Raspeln&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_rezept&quot;&gt;Rezept&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_pudding_für_die_buttercreme&quot;&gt;Pudding (für die Buttercreme)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_dunkler_wiener_boden&quot;&gt;Dunkler Wiener Boden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_schokoraspeln&quot;&gt;Schokoraspeln&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_kirschen&quot;&gt;Kirschen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_buttercreme&quot;&gt;Buttercreme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_zusammenbau_der_torte&quot;&gt;Zusammenbau der Torte&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Dynamic AsciiDoc with Groovy and jBake</title>
      <link>https://fiveandahalfstars.ninja/blog/2020/2020-11-11-Dynamic-AsciiDoc.html</link>
      <pubDate>Wed, 11 Nov 2020 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2020/2020-11-11-Dynamic-AsciiDoc.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Did you ever wish to be able to create more &quot;dynamic&quot; documents with AsciiDoc?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_attributes&quot;&gt;Attributes&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Attributes are already quite nice.
They let you create parameterized docs which you can easily update.
One example on how to use attributes are URIs for links in your document.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For example, if you have a reference like&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;asciidoc&quot;&gt;https://fiveandahalfstars.ninja/blog/2020/greenscreen_fuer_online-besprechungen_selbst_bauen[latest post by Johannes]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;you can replace this with the following, more readable version&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;asciidoc&quot;&gt;:uri1: https://fiveandahalfstars.ninja/blog/2020/greenscreen_fuer_online-besprechungen_selbst_bauen

{uri1}[latest post by Johannes]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And whenever the link has to be updated (because Johannes published something new), you just have to update the attribute and the link will change wherever it was used.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_jbake_meta_data&quot;&gt;jBake Meta-Data&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In additon to the AsciiDoc attributes, jBake comes with a &lt;a href=&quot;https://jbake.org/docs/2.6.4/#metadata_header&quot;&gt;Metadata-Header&lt;/a&gt;.
We use this for instance to tag a post with an author.
These meta-data snippets are also AsciiDoc attributes.
In addtion, you can access them in the page templates.
Here is a snippet from our &lt;code&gt;postpreview.gsp&lt;/code&gt; template:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&amp;lt;img src=&quot;images/profiles/${post.author}.jpg&quot; alt=&quot;${post.author}&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_jbake_data_model&quot;&gt;jBake Data-Model&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Another concept of jBake is to first parse and store all content in a local database and only then apply the templates.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This turns every blog post into one line of a data table.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_chunks_of_data&quot;&gt;Chunks of Data&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now, what happens if you have more data?
Or maybe you don&amp;#8217;t want to create an extra file for each data entry?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Maybe you want to display the latest measurements of your IoT device or you have a list of talks (like we have) and you want to render them?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In case of the talks, we started out to maintain them as pure AsciiDoc files.
That is ok for a start.
The list might grow quite quickly and as soon as you want to display such a (long) list in another way, you need to reformat &lt;em&gt;all&lt;/em&gt; entries.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In case of the measurements of your IoT device, it is even more obvious - you just don&amp;#8217;t want to type the measuremts by hand into an AsciiDoc table.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_two_solutions&quot;&gt;Two Solutions&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To automate things, there are two solutions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_one_a_generator&quot;&gt;One: a Generator&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You already &lt;em&gt;build&lt;/em&gt; your docs, so why not convert some json formatted data into AsciiDoc &lt;em&gt;before&lt;/em&gt; you hand it over to jBake?
In fact, this is a pretty easy approach, depending on the language you use.
And for both use cases, it is easier to maintain your data as json file than as AsciiDoc (which is in fact not a data-format 😁).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Code for this could look somthing like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;title&quot;&gt;generate.groovy&lt;/div&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;groovy&quot;&gt;//read data file
def json = new File(content.datafile).text
def data = new groovy.json.JsonSlurper().parseText(json)
//iterate over data and output list of talks
def asciidoc = &quot;&quot;
data.talks.each { talk -&amp;gt;
    asciidoc += &quot;&quot;&quot;\
== ${talk.date} ${talk.title}

${talk.abstract}

&quot;&quot;&quot;
}
new File(&quot;talks.adoc&quot;).write(asciidoc)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can then include the result in any &lt;code&gt;.adoc&lt;/code&gt;-file.
As you can see, it is now easy to (for instance) add the location where the talk will happen or any other detail.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_two_dynamic_asciidoc&quot;&gt;Two: Dynamic AsciiDoc&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Do you know PHP, JSP or GSP?
With those server-side template languages, you have a syntax which lets you add dynamic elements to an otherwise static template.
The generator code seen above could look like&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;title&quot;&gt;talks.adoc&lt;/div&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;asciidoc&quot;&gt;:jbake-type: gsp
:jbake-dataFile: ./data/talks.json

&amp;lt;% talks.each { talk -&amp;gt; %&amp;gt;

== ${talk.date} ${talk.title}

${talk.abstract}

&amp;lt;% } %&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The main difference is now, we inject code within &amp;lt;% &amp;#8230;&amp;#8203; %&amp;gt; into our document instead the other way around.
The code shown could be embedded in a larger document and since this is part of the document, you don&amp;#8217;t have to start an additional build step before your build your docs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &lt;code&gt;:jbake-dataFile:&lt;/code&gt; specifies where our data comes from.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;jBake already implements GSP-Templates.
Groovy Server Pages.
These allow us to use Groovy code within our templates.
And this allows us to use also the body of a document as GSP-Template.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Such a template looks like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;prettyprint highlight&quot;&gt;&lt;code data-lang=&quot;gsp&quot;&gt;&amp;lt;%include &quot;header.gsp&quot;%&amp;gt;
&amp;lt;body onload=&quot;prettyPrint()&quot;&amp;gt;
&amp;lt;div id=&quot;wrap&quot;&amp;gt;
    &amp;lt;%include &quot;menu.gsp&quot;%&amp;gt;
    &amp;lt;div class=&quot;container&quot;&amp;gt;

        &amp;lt;%
            def template
            def body = &quot;&quot;
            try {
                //read data file
                def json = new File(content.datafile).text
                def data = new groovy.json.JsonSlurper().parseText(json)
                //combine data and template
                def engine = new groovy.text.SimpleTemplateEngine()
                // clean up the body
                // (Asciidoctor replaces a bit too much)
                body = content.body
                        .replaceAll(&quot;&amp;amp;#8594;&quot;, &quot;-&amp;gt;&quot;)
                        .replaceAll(&quot;&amp;amp;#8656;&quot;, &quot;&amp;lt;=&quot;)
                        .replaceAll(&quot;&amp;amp;lt;&quot;, &quot;&amp;lt;&quot;)
                        .replaceAll(&quot;&amp;amp;gt;&quot;, &quot;&amp;gt;&quot;)
                        .replaceAll(&quot;&amp;amp;amp;&quot;, &quot;&amp;amp;&quot;)
                template = engine.createTemplate(body).make(data)
            } catch (Exception e) {
                out &amp;lt;&amp;lt; &quot;&amp;lt;pre&amp;gt;&quot;
                out &amp;lt;&amp;lt; e.message
                out &amp;lt;&amp;lt; body
                out &amp;lt;&amp;lt; e.getStackTrace().join(&quot;\n&quot;)
                out &amp;lt;&amp;lt; &quot;&amp;lt;/pre&amp;gt;&quot;
            }
        %&amp;gt;

        &amp;lt;%= template %&amp;gt;

    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;%include &quot;footer.gsp&quot;%&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;et voilà! Dynamic AsciiDoc!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock important&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;i class=&quot;fa icon-important&quot; title=&quot;Important&quot;&gt;&lt;/i&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
The solution shown is a good solution for some use cases, like the ones mentioned above.
Please keep in mind that the resulting AsciiDoc is not standard conform anymore and will only work with your jBake system.
The generator approach might be a better solution in certain situations.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2020/2020-11-teaser.png&quot; alt=&quot;2020 11 teaser&quot; width=&quot;0&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;toc&quot; class=&quot;toc&quot;&gt;
&lt;div id=&quot;toctitle&quot; class=&quot;title&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul class=&quot;sectlevel1&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_attributes&quot;&gt;Attributes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_jbake_meta_data&quot;&gt;jBake Meta-Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_jbake_data_model&quot;&gt;jBake Data-Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_chunks_of_data&quot;&gt;Chunks of Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_two_solutions&quot;&gt;Two Solutions&lt;/a&gt;
&lt;ul class=&quot;sectlevel2&quot;&gt;
&lt;li&gt;&lt;a href=&quot;#_one_a_generator&quot;&gt;One: a Generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#_two_dynamic_asciidoc&quot;&gt;Two: Dynamic AsciiDoc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Build your own Webcam - Part 3</title>
      <link>https://fiveandahalfstars.ninja/blog/2020/2020-08-29-build-your-own-webcam-part-3.html</link>
      <pubDate>Sat, 29 Aug 2020 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2020/2020-08-29-build-your-own-webcam-part-3.html</guid>
      <description>
      &lt;p&gt;We are still in a situation where working from home is the normal situation.&lt;br /&gt;
And while maybe you already got enough webcams to solve your conferencing problems, here are two new ideas.&lt;/p&gt;
&lt;h2&gt;1. HDMI Capture Cards&lt;/h2&gt;
&lt;p&gt;A HDMI capture card was always something I dreamed of but 120 € was too much to just play around with it.&lt;/p&gt;
&lt;p&gt;Now, the price has changed.&lt;/p&gt;
&lt;p&gt;There are currently some new chinese, no-name capture cards on the market for as low as 15 €!&lt;/p&gt;
&lt;h3&gt;Are they worth it?&lt;/h3&gt;
&lt;p&gt;Yes! They are able to capture HDMI at 1920x1080 with 30fps and only a short delay. If you lower the resolution, you even get 60fps.&lt;br /&gt;
And what&apos;s best about them, you plug them in as USB device and they pretend to be a webcam.&lt;br /&gt;
No additional drivers needed.&lt;/p&gt;
&lt;p&gt;Just search on amazon for &lt;a href=&quot;https://www.amazon.de/s?k=hdmi+capture+card&quot;&gt;&amp;quot;HDMI capture card&amp;quot;&lt;/a&gt; and you&apos;ll find them.&lt;br /&gt;
There are even once with a HDMI output to connect an additional monitor.&lt;/p&gt;
&lt;h3&gt;What does this have to do with a Webcam?&lt;/h3&gt;
&lt;p&gt;Glad you ask ;-)&lt;/p&gt;
&lt;p&gt;With a HDMI Capture Card, you can...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;... use any DSLR with HDMI out as Webcam. And since the Canon driver is only available for Windows, you can even use Canon cameras with your Mac&lt;/li&gt;
&lt;li&gt;... use a second PC to do the heavy OBS lifting and feed the output as Webcam to the PC on which you do your video conferencing.&lt;/li&gt;
&lt;li&gt;... use a tablet like the iPad with HDMI out as white board for your sessions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Isn&apos;t that cool?&lt;/p&gt;
&lt;h2&gt;2. Use your Pi-Zero as real Webcam&lt;/h2&gt;
&lt;p&gt;In my last blog posts, I tried to set up a pizero based webcam, but it needed to many additional drivers and the performance varied over the network.&lt;br /&gt;
I didn&apos;t think of the feature that the pizero (and only the pizero, no other model yet) can act as an usb device itself.&lt;br /&gt;
But now I found a great blog post which desccribes exactly this: &lt;a href=&quot;http://www.davidhunt.ie/raspberry-pi-zero-with-pi-camera-as-usb-webcam/&quot;&gt;turn the pizero in a usb webcam&lt;/a&gt;.&lt;br /&gt;
Since modern operating systems already include drivers for webcams, no additional drivers are needed.&lt;/p&gt;
&lt;p&gt;The results as presented in the video from the blog author look very promising:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/idD61VOJ024&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Now, this will allow me to create an IR-Webcam with th PiNoIR camera - that&apos;ll be fun!&lt;/p&gt;
&lt;p&gt;PS: thanx to &lt;a href=&quot;https://twitter.com/johannesdienst&quot;&gt;Johannes Dienst&lt;/a&gt; for fixing my typos :-)&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Greenscreen für Online-Besprechungen selbst bauen</title>
      <link>https://fiveandahalfstars.ninja/blog/2020/Greenscreen_fuer_Online-Besprechungen_selbst_bauen.html</link>
      <pubDate>Fri, 3 Jul 2020 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2020/Greenscreen_fuer_Online-Besprechungen_selbst_bauen.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wer sich mit dem Thema Video-Streaming beschäftigt kennt sie unweigerlich: Greenscreens. Aber auch in der Zeit der Online-Meetings
und Zuhausearbeit kann mit ein klein wenig Aufwand ein Online-Meeting aufgepeppt werden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In diesem Beitrag zeige ich, wie ich es unter ungünstigen Bedingungen geschafft habe das folgende Ergebnis in Microsoft Teams zu erreichen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2020/Virtual_cam_teams.png&quot; alt=&quot;Microsoft Teams Screenshot mit virtueller Kamera OBS Studio&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. Endergebnis in Microsoft Teams mit virtueller Kamera aus OBS Studio&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_voraussetzungen&quot;&gt;Voraussetzungen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wie auf dem unteren Bild zu sehen, ist mein Platzangebot sehr gering. Da ich direkt unter dem Dach mein Arbeitszimmer habe,
fällt die Möglichkeit weg, den Greenscreen weit von mir weg zu platzieren. Das hat die folgenden Nachteile:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Die Wahrscheinlichkeit des sogenannten Greenspills, also dem Zurückwerfen der grünen Farbe auf mich, ist sehr hoch. Ich werde also einen grünen Rand von wenigen Pixeln um mich herum haben.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Der Greenscreen kann bei entsprechender Höhe nicht breit genug werden&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2020/Camera_under_roof.jpg&quot; alt=&quot;Bild von mir an meinem Schreibtisch unter dem Dach&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 2. Nicht viel Platz unterm Dach&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_was_wird_gebraucht&quot;&gt;Was wird gebraucht&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Für mich persönlich fällt in diesem Szenario ein gekaufter Greenscreen flach. Selbstmachen und hoffen war angesagt :)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dafür habe ich mich umgesehen und bin bei IKEA fündig geworden. Hier die Einkaufsliste (Keine Affiliate Links):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ikea.com/de/de/p/rigga-garderobenstaender-weiss-50231630/&quot;&quot;&gt;Garderobenständer RIGGA&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ikea.com/de/de/p/oddhild-plaid-leuchtend-gruen-10465089/&quot;&gt;Zweimal Decke Oddhild in leuchtend grün&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ikea.com/de/de/p/torkis-waescheklammern-blau-70458670/&quot;&gt;Wäscheklammern (falls nicht vorhanden)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Gesamtkosten: ca. 21 €&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zur Erklärung: Der Garderobenständer Rigga passte von der Breite perfekt in mein Dachgeschoss und ist zusätzlich höhenverstellbar.
Die Breite ist jedoch ein Problem, auf das ich später noch näher eingehen werde. Bei der Decke war klar, dass sie sehr lichtdurchlässig ist.
Deswegen bin ich auf Nummer sicher gegangen und habe zwei Exemplare bestellt. Das hat sich als gute Idee herausgestellt!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_zusammenbau&quot;&gt;Zusammenbau&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Den Garderobenständer zusammenzuschrauben ist mit handwerklichen Geschick möglich. Die Deckenbefestigung an ihm ein klein wenig hakelig
da beides sehr glatt ist. Es empfiehlt sich zuerst eine Decke zu befestigen und dann die zweite. Ich habe das pragmatisch gelöst - nicht
unbedingt hübsch (siehe Bild)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2020/Befestigung_Decke_Waescheklammern.jpg&quot; alt=&quot;Befestigung der Decken mit Wäscheklammern am Garderobenständer&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 3. Befestigung der Decken mit Wäscheklammern am Garderobenständer&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_das_setup&quot;&gt;Das Setup&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Der Greenscreen ist jetzt schon bereit, um ihn hinter mir zu platzieren. Aufgrund der Gegebenheiten steht er so nah bei mir, dass er am Stuhl anliegt.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2020/Greenscreen_Setup_raw.png&quot; alt=&quot;Greenscreensetup direkt hinter Stuhl&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 4. Greenscreensetup direkt hinter Stuhl&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_verwendung_in_videokonferenzsoftware_mit_virtueller_kamera_aus_obs_studio&quot;&gt;Verwendung in Videokonferenzsoftware (Mit virtueller Kamera aus OBS Studio)&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Viele Videokonferenzprogramme bieten die Möglichkeit, Hintergrundbilder einzublenden. Meistens wird der Sprecher anhand eines Algorithmus erkannt.
Das ist dann je nach Bildhintergrund, den die Kamera aufnimmt, nicht perfekt. Arme verschwinden, Artefakte entstehen um den Kopf und um Gliedmaßen
und Durchscheinen des Zimmers sind hier Standard.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Am Beispiel von Microsoft Teams zeige ich das Ergebnis, wenn stattdessen ein Greenscreen verwendet wird und mit &lt;a href=&quot;https://obsproject.com/de&quot;&gt;OBS Studio&lt;/a&gt; eine virtuelle Kamera in Teams eingebunden wird.
Mit ihr, habe ich auch die Breite so zugeschnitten, dass keine Ränder zu sehen sind. (Teaser: Wie das eingerichtet wird, beschreibe ich in einem weiteren Beitrag).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../../images/content/2020/Virtual_cam_teams.png&quot; alt=&quot;Microsoft Teams Screenshot mit virtueller Kamera OBS Studio&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 5. Endergebnis in Microsoft Teams mit virtueller Kamera aus OBS Studio&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_streulicht_und_beleuchtung&quot;&gt;Streulicht und Beleuchtung&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Für das oben erreichte Ergebnis wurden noch ein paar Vorkehrungen getroffen, um den Greenscreen gleichmäßiger auszuleuchten.
Je gleichmäßiger er ausgeleuchtet ist, desto besser!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Alle Türen schließen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alle Rolläden herunter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vorhänge schließen&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Optional: Softboxen (hier reichen billige; Meine haben 50 € gekostet)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_greenspill&quot;&gt;Greenspill&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Leider lässt sich mit meinem Setup der Greenspill nicht vermeiden. Der Greenscreen ist einfach zu nahe an mir dran.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2020/Greenspill.png&quot; alt=&quot;An der Hand ist der Greenspill deutlich zu erkennen&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 6. An der Hand ist der Greenspill deutlich zu erkennen&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_was_geht_noch&quot;&gt;Was geht noch?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In einem weiteren Beitrag werde ich das Tool &lt;a href=&quot;https://obsproject.com/de&quot;&gt;OBS Studio&lt;/a&gt; vorstellen und zeigen, dass der Greenscreen wunderbar für Livecoding, Konferenzen und Workshops eingesetzt werden kann.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bis bald!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Build your own Webcam - Part 2</title>
      <link>https://fiveandahalfstars.ninja/blog/2020/2020-05-16-build-your-own-webcam-part-2.html</link>
      <pubDate>Sat, 16 May 2020 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2020/2020-05-16-build-your-own-webcam-part-2.html</guid>
      <description>
      &lt;p&gt;As promised, I gave some of the tutorials from my last post a try.&lt;br /&gt;
Here is what I learned so far.&lt;/p&gt;
&lt;h3&gt;Video Source&lt;/h3&gt;
&lt;h4&gt;Android&lt;/h4&gt;
&lt;p&gt;For android based devices, it seems that &lt;a href=&quot;http://ip-webcam.appspot.com/&quot;&gt;IP-Webcam&lt;/a&gt; is quite a good choice.&lt;br /&gt;
The website looks quite basic but the software itself works great and provides lots of options!&lt;br /&gt;
When you start it on your phone, the phone will spin up a webserver which you then can connect to with any other device on your network (make sure that it is only accessible from your trusted network!)&lt;br /&gt;
and it gives you lots of options.&lt;/p&gt;
&lt;p&gt;It also comes with a simple driver for this IP based webcam for your PC.&lt;/p&gt;
&lt;h4&gt;Raspberry Pi&lt;/h4&gt;
&lt;p&gt;Since I had a Raspberry Pi Zero and a camera lying around, I thought it would be fun to turn it into a webcam.&lt;br /&gt;
It was quite clear from the start that the Pi Zero does not have too much power but I thought it is ok to give it a try.&lt;/p&gt;
&lt;p&gt;To cut the long story short, here is what I learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;network connection&lt;/li&gt;
&lt;li&gt;you can connect the Pi Zero over WiFi or through a usb based network connection (the pi plays the role of a network adapter which only works with the zero or pi 4)&lt;/li&gt;
&lt;li&gt;the usb connection has less lag and more throughput than the WiFi connection&lt;/li&gt;
&lt;li&gt;the throughput is still the bottleneck for high-quality, high frame-rate video&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jacksonliam/mjpg-streamer&quot;&gt;mjpg-streamer&lt;/a&gt; is a powerful tool to turn your pi into a network camera! It also comes with a cool web interface&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/mjpegstreamer.png&quot; style=&quot;max-width:100%;&quot; /&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;lighting - since I wanted to capture the image of some scribbles on paper with this camera, I wanted to have good illumination. So, I remembered that I have an ultra-bright LED display for the pi zero. These LEDs have a very cold light and I didn&apos;t manage to set up the white balance to compensate for that.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Result: it was fun to play around with the Pi, but it is not a solution :-)&lt;/p&gt;
&lt;h3&gt;Software needed on the PC&lt;/h3&gt;
&lt;h4&gt;ManyCam&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://manycam.com/&quot;&gt;ManyCam&lt;/a&gt; seems to be a nice and easy to use solution with many options and effects.&lt;br /&gt;
But it also comes with a price tag.&lt;br /&gt;
The pricing plan I would go for is the lifetime studio version for which the price is $119. :-o&lt;/p&gt;
&lt;p&gt;ManyCam not just provides a virtual cam for IP based sources, it can also bring together a bunch of other sources, present them as picture in picture, lets you switch through scenes and even lets you add a timer or other effects.&lt;br /&gt;
So, if you are willing to pay the price, this tools seems to be quite fun!&lt;/p&gt;
&lt;h4&gt;SplitCam&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://splitcam.com/&quot;&gt;SplitCam&lt;/a&gt; does not provide as many features as ManyCam and it also didn&apos;t look too trustworthy.&lt;br /&gt;
When I read the first blog post &amp;quot;How to add StripChat Stream&amp;quot;, I knew that I am not the target group :-)&lt;/p&gt;
&lt;p&gt;I didn&apos;t try the other tools mentioned in the tutorials, because I had another idea:&lt;/p&gt;
&lt;h4&gt;OBS Studio&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://obsproject.com/&quot;&gt;OBS Studio&lt;/a&gt; is an open source and free tool which I already use to record my talks.&lt;/p&gt;
&lt;p&gt;There is a &lt;a href=&quot;https://obsproject.com/forum/resources/obs-virtualcam.949/&quot;&gt;virtual camera plugin for OBS&lt;/a&gt; which lets you select the OBS output as webcam input in most video chat solutions.&lt;br /&gt;
This allows me to take some input and re-use it as webcam!&lt;/p&gt;
&lt;p&gt;I also found out that it supports a VLC video source as input.&lt;br /&gt;
This works in such a way that OBS uses the VLC libraries to display a network stream like VLC - VLC itself does not have to be running.&lt;br /&gt;
Unfortunately, this turns out to be quite laggy and thus unusable in a live environment.&lt;/p&gt;
&lt;h4&gt;OBS Ninja to the rescue&lt;/h4&gt;
&lt;p&gt;As reaction to my last post, &lt;a href=&quot;https://twitter.com/d_pisanu&quot;&gt;Daniel Pisanu&lt;/a&gt; mentioned &lt;a href=&quot;https://obs.ninja&quot;&gt;obs.ninja&lt;/a&gt; as a solution.&lt;br /&gt;
It is really cool, but I needed some help to get it up and running.&lt;br /&gt;
This was basically because I didn&apos;t understand the solution at first.&lt;/p&gt;
&lt;p&gt;The website builds up a video chat connection between any two webRTC capable devices.&lt;br /&gt;
As result, you will get a peer-to-peer video stream in your browser.&lt;br /&gt;
It works quite like jitsi.&lt;/p&gt;
&lt;p&gt;First, I tried to get the room functionality to work and didn&apos;t succeed, but if you use the big &amp;quot;Create Reusable Invite&amp;quot; button, it works like a charm.&lt;/p&gt;
&lt;p&gt;You can even share your desktop this way.&lt;/p&gt;
&lt;p&gt;Since it is browser based, you can add nearly every WiFi connected device as video source.&lt;br /&gt;
Even those cheap Amazon kindle fire tablets!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.de/8-Tablet-Alexa-8-Zoll-HD-Display-Schwarz-Spezialangeboten/dp/B0794X2TM4/ref=as_li_ss_il?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;dchild=1&amp;keywords=kindle+fire&amp;qid=1589612010&amp;sr=8-1&amp;linkCode=li1&amp;tag=bit0c-21&amp;linkId=3799d8a96f026b27d6d214f851edca4e&amp;language=de_DE&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;//ws-eu.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;ASIN=B0794X2TM4&amp;Format=_SL110_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=bit0c-21&amp;language=de_DE&quot; &gt;&lt;/a&gt;&lt;img src=&quot;https://ir-de.amazon-adsystem.com/e/ir?t=bit0c-21&amp;language=de_DE&amp;l=li1&amp;o=3&amp;a=B0794X2TM4&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now, the next step is to add this stream to your OBS scene.&lt;br /&gt;
To do so, add a web-browser as source and point it to your OBS-Ninja link.&lt;br /&gt;
As a result, you will get a high quality stream with only a tiny lag within OBS!&lt;/p&gt;
&lt;p&gt;And this works for other web based resources too!&lt;br /&gt;
It even turns out that you can use the stream URL of your raspberry pi cam to workouround the laggy VLC input.&lt;br /&gt;
Or add a nice timer through &lt;a href=&quot;http://timer.digital-wachsen.de/&quot;&gt;timer.digital-wachsen.de&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, OBS is the way to go for me now!&lt;/p&gt;
&lt;h3&gt;What about the digital cameras?&lt;/h3&gt;
&lt;p&gt;I also went through my box of old digital cameras and it turned out that none of it had web cam features.&lt;/p&gt;
&lt;p&gt;But yesterday I saw that you can get a Canon EOS 2000D for as cheap as 299€ and I read that the Cannon webcam utility should work with that camera.&lt;br /&gt;
So, I ordered it and will see....&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I&apos;ve got my EOS camera and it works well. You have to learn how to handle it (sometimes it does not recognize the camera because it seems to be blocked from another session or the EOS utility - exit it before you use the EOS as webcam). But the result is a sharp and high quality picture!&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;For me as techhie, OBS is the way to go, but it is not a solution for everyone.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://obs.ninja&quot;&gt;OBS.ninja&lt;/a&gt; is a great solution for remote sources.&lt;/p&gt;
&lt;p&gt;Regarding the webcam hardware, I am quite happy with the quality of my logitec C920, but I am also eager to try the Canon EOS as new high quality webcam.&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Build your own Webcam</title>
      <link>https://fiveandahalfstars.ninja/blog/2020/2020-05-01-build-your-own-webcam.html</link>
      <pubDate>Fri, 1 May 2020 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2020/2020-05-01-build-your-own-webcam.html</guid>
      <description>
      &lt;p&gt;Before Corona, I was quite happy with my build-in webcam together with an additional external logitec C920HD.&lt;br /&gt;
The logitec mainly replaced my build-in cam for my company notebook - it has a far better quality.&lt;/p&gt;
&lt;p&gt;But now, that I am forced to do everything online, two webcams are not enough.&lt;br /&gt;
The logitech is now mounted above some sheets of paper as a replacement for a whiteboard.&lt;br /&gt;
For the online piano lessons of my son, I need two additioanal webcams with a special setup.&lt;/p&gt;
&lt;p&gt;So, I need more webcams than I currently have but no additional webcams are available through online stores :-(&lt;/p&gt;
&lt;p&gt;Time to re-think the solution!&lt;/p&gt;
&lt;h3&gt;Old Smartphones as webcam&lt;/h3&gt;
&lt;p&gt;Golem.de created a good (german) article about solutions which &lt;a href=&quot;https://www.golem.de/news/webcam-alternativen-angeschaut-das-smartphone-als-webcam-nutzen-2004-147863.html&quot;&gt;use smartphones as webcams&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;TL;DR: &lt;a href=&quot;https://www.kinoni.com/#&quot;&gt;EpocCam&lt;/a&gt;, &lt;a href=&quot;http://www.dev47apps.com/&quot;&gt;DroidCam&lt;/a&gt; and &lt;a href=&quot;https://manycam.com/&quot;&gt;ManyCam&lt;/a&gt; are the proposed solutions.&lt;/p&gt;
&lt;h3&gt;Raspberry Pi as webcam&lt;/h3&gt;
&lt;p&gt;Another interesting solution is to utilize one of those many raspberries I bought and never used.&lt;/p&gt;
&lt;p&gt;Google provides tutorials for this solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://raspberrytips.com/raspberry-pi-camera-as-webcam/&quot;&gt;Raspberry Tips: Pi Camera as Webcam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tomshardware.com/how-to/use-raspberry-pi-as-pc-webcam&quot;&gt;Toms Hardware: Use Raspberry Pi as PC Webcam&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both tutorials are a bit different but both use the raspberry as network based camera.&lt;br /&gt;
This means it is the same approach as with the smartphone.&lt;/p&gt;
&lt;p&gt;For me, the main question now is, if there is a PC software / driver which is capable to use both - the smartphone and the raspberry - as a webcam.&lt;/p&gt;
&lt;p&gt;When your Raspberry is set up and ready to go, you will find more ideas to play around with it in the &lt;a href=&quot;https://magpi.raspberrypi.org/books/camera-guide&quot;&gt;official camra guide&lt;/a&gt; - great ressource!&lt;/p&gt;
&lt;p&gt;Stay tuned because I will soon write about my experience...&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; &lt;a href=&quot;https://twitter.com/phaus/status/1256290854756646914&quot;&gt;@phaus&lt;/a&gt; mentioned on twitter that Canon is updating their cameras to double as webcam.&lt;br /&gt;
Maybe I should check my old cameras to see if I could use them as webcams, too!&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>How to Self-Record your Conference Talk</title>
      <link>https://fiveandahalfstars.ninja/blog/2020/2020-03-09-self-record-your-talk.html</link>
      <pubDate>Mon, 9 Mar 2020 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2020/2020-03-09-self-record-your-talk.html</guid>
      <description>
      &lt;p&gt;Some time ago, I attended a talk by Bernd Rücker.&lt;br /&gt;
I can&apos;t remember the talk anymore (probably something about workflows and decisions),&lt;br /&gt;
but I remember that he set up a camera and self-recorded his talk.&lt;br /&gt;
After the talk, he used the coffee break to post-process the video and upload it to youtube.&lt;/p&gt;
&lt;p&gt;He has written a short blog on &lt;a href=&quot;https://blog.bernd-ruecker.com/how-i-record-my-own-talks-dee7903c2d53&quot;&gt;how he records his talks&lt;/a&gt; and so I started my journey.&lt;/p&gt;
&lt;h3&gt;Here is my experience so far...&lt;/h3&gt;
&lt;p&gt;I started with Camtasia because I got a cheap copy through Humble Bundle (since I do this as a hobby, my decisions are quite price-sensitive).&lt;br /&gt;
But I am not quite happy with Camtasia for recording since it draws quite a lot of CPU power.&lt;br /&gt;
It sometimes slows my machine down to the point where you can see characters slowly pop up while I type.&lt;br /&gt;
Not good.&lt;/p&gt;
&lt;p&gt;So I searched for another recording tool and found &lt;a href=&quot;https://obsproject.com/&quot;&gt;Open Broadcaster Software (OBS)&lt;/a&gt;.&lt;br /&gt;
This tool is optimized for gamers who want to stream their gaming experience live to twitch and other channels.&lt;br /&gt;
This implies that it does not draw too much CPU resources.&lt;/p&gt;
&lt;p&gt;It also works quite nicely to record your various video and audio sources.&lt;br /&gt;
The main drawback is that it is not very intuitive to use, so here are some tips and tricks:&lt;/p&gt;
&lt;h4&gt;record multiple video sources&lt;/h4&gt;
&lt;p&gt;OBS does not record multiple video sources to multiple files.&lt;br /&gt;
It only records one video with multiple sources layed out.&lt;br /&gt;
This allows you to record your main presentation screen (the projector) and overlay the speaker video as a small webcam video on top of it.&lt;/p&gt;
&lt;p&gt;However, this way you have to first decide about the layout of your video.&lt;br /&gt;
The decision will be final.&lt;br /&gt;
I wanted to have more freedom, so I found the following trick:&lt;/p&gt;
&lt;p&gt;Create a canvas which is big enough to place all your source on it and record them side by side.&lt;br /&gt;
This allows you to record all video sources in one file and separate the sources later.&lt;/p&gt;
&lt;p&gt;The following video shows this concept:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/O8w9x31FBUo&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h4&gt;record multiple audio sources&lt;/h4&gt;
&lt;p&gt;I thought it was enough to record one audio source - my speaker microphone (see below for details), but I was wrong.&lt;br /&gt;
The last time I tried to record my talk, I only noticed afterward that I recorded the wrong audio source.&lt;br /&gt;
This turned the whole recording to be worthless.&lt;/p&gt;
&lt;p&gt;So I searched for a solution on how to record all available microphone - webcam, speaker-mic and build in.&lt;br /&gt;
Just to be sure.&lt;/p&gt;
&lt;p&gt;The solution is to first choose an output format that is capable to record multiple audio channels.&lt;br /&gt;
The details are explained in the following video:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/ZdFeCaStTbw&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h4&gt;set up all sources&lt;/h4&gt;
&lt;p&gt;One day I tried to set up my recording upfront but I wasn&apos;t able to set up the speaker screen but OBS didn&apos;t who me the second screen as a source.&lt;br /&gt;
This was when I found out that it only shows sources which are already connected to your notebook.&lt;/p&gt;
&lt;p&gt;The next time, I knew that I had the perfect setup from two days before and I relied on this setup in another location.&lt;br /&gt;
Unfortunately, the setup was created with a low-res projector in the first location and the second location had a high-res projector.&lt;br /&gt;
So I only recorded the upper left quarter of the screen :-(.&lt;/p&gt;
&lt;p&gt;OBS seems also to have problems when you disconnect and then reconnect devices (USB webcam).&lt;br /&gt;
Even when I just close my notebook and re-open it, the internal webcam does not work as a source anymore and I have to re-setup it.&lt;/p&gt;
&lt;p&gt;So, here is my tip: when it is your turn, try to be at the location 15 minutes before and setup OBS individually for the location and leave your notebook up and running.&lt;br /&gt;
You might even want to already start your recording in order not to forget it when your talk starts.&lt;/p&gt;
&lt;h3&gt;Hardware&lt;/h3&gt;
&lt;h4&gt;Camera&lt;/h4&gt;
&lt;p&gt;As a camera, I use the same Logitech HD 920 pro as Bernd.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.de/Logitech-C920-HD-Pro-Webcam-Videogespr%C3%A4che-Videoaufnahmen-Full-HD-Stereo-Mikrofonen/dp/B006A2Q81M/ref=as_li_ss_il?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;crid=3T196WPSINTUA&amp;keywords=logitech+920&amp;qid=1583760314&amp;sprefix=logitech+920,aps,262&amp;sr=8-3&amp;linkCode=li2&amp;tag=bit0c-21&amp;linkId=ae780829066894f97affbb9a639fdfd8&amp;language=de_DE&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;//ws-eu.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;ASIN=B006A2Q81M&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=bit0c-21&amp;language=de_DE&quot; &gt;&lt;/a&gt;&lt;img src=&quot;https://ir-de.amazon-adsystem.com/e/ir?t=bit0c-21&amp;language=de_DE&amp;l=li2&amp;o=3&amp;a=B006A2Q81M&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It has a great video quality and the microphones record a full room.&lt;br /&gt;
So if your speaker mic has problems, the webcam mics are a good fall back.&lt;/p&gt;
&lt;p&gt;A cheap camera stand (like the one mentioned by Bernd) is enough to mount it in most situations and it is easy to carry.&lt;/p&gt;
&lt;h4&gt;Microphone&lt;/h4&gt;
&lt;p&gt;A cheap &lt;a href=&quot;https://amzn.to/2W3Rtkt&quot;&gt;lavalier or lapel microphone for ~10€&lt;/a&gt; is a great choice to record your voice.&lt;br /&gt;
I will only record your voice and not the whole room as the webcam does.&lt;br /&gt;
And in most situations, you don&apos;t need a wireless mic.&lt;br /&gt;
The cable of these cheap mics is long enough to give you some freedom to move a bit behind your notebook and they are just far cheaper than wireless mics.&lt;/p&gt;
&lt;p&gt;You could also use a bluetooth headset, but the sound quality is not as good since the loudspeaker and mic share the frequency band over one bluetooth connection.&lt;/p&gt;
&lt;h4&gt;Presenter&lt;/h4&gt;
&lt;p&gt;When you are used to a laser pointer as a presenter, keep in mind that the laser pinter will not be recorded through your screen recording.&lt;br /&gt;
And the quality of your camera will not be good enough to capture the projected screen.&lt;br /&gt;
Even with a decent camera, the camera has to cope with the light conditions.&lt;/p&gt;
&lt;p&gt;That&apos;s why I use a Logitech Spotlight as presenter:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.de/Logitech-Fortschrittliche-Pr%C3%A4sentationsfernbedienung-universell-Schnellladefunktion/dp/B06WP4QCKT/ref=as_li_ss_il?__mk_de_DE=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;crid=3FWZFZ38KHE8I&amp;keywords=spotlight+presenter&amp;qid=1583760845&amp;sprefix=spotlight+presen,aps,270&amp;sr=8-3&amp;linkCode=li2&amp;tag=bit0c-21&amp;linkId=9086cb72d41147a148faee52529f4eca&amp;language=de_DE&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;//ws-eu.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;ASIN=B06WP4QCKT&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=bit0c-21&amp;language=de_DE&quot; &gt;&lt;/a&gt;&lt;img src=&quot;https://ir-de.amazon-adsystem.com/e/ir?t=bit0c-21&amp;language=de_DE&amp;l=li2&amp;o=3&amp;a=B06WP4QCKT&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Not cheap but super cool!&lt;/p&gt;
&lt;h3&gt;Post-Processing&lt;/h3&gt;
&lt;p&gt;OBS helps you to record your talk but it will not do any post-processing.&lt;br /&gt;
That&apos;s where Camtasia shines.&lt;br /&gt;
It is a simple tool to cut, edit and re-render your final video.&lt;br /&gt;
It also does the trick to import your recorded video (screen + webcam) twice and clip it to separate the two sources.&lt;/p&gt;
&lt;h3&gt;Other Tips &amp;amp; Tricks&lt;/h3&gt;
&lt;p&gt;When I started, someone told me that I could record different sources with different devices.&lt;br /&gt;
&amp;quot;Just clap your hand at the start of your recording and it will be easy to synchronize the sources.&amp;quot;&lt;/p&gt;
&lt;p&gt;So I recorded my voice with my mobile phone (yes, freedom to move around!) and video with an action cam.&lt;/p&gt;
&lt;p&gt;Yes, you will easily find your hand-clap in the video and audio channel, but it turned out that the different sources diverged some minutes(!) after a one hour talk.&lt;br /&gt;
That&apos;s why I only record with one device - my speaker notebook - since then.&lt;/p&gt;
&lt;p&gt;Hope this blog might help you with your own recordings!&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Präsentationen Best Practices</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/Praesentationen_Best_Practices.html</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/Praesentationen_Best_Practices.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Manchen Sprechern hört man einfach gerne zu und bei anderen möchte man trotz eines interessanten Themas einfach nur
den Raum verlassen. Viele Dinge beim Vortragen kommen mit der Zeit. Darunter fällt für mich die nötige Gelassenheit,
eine klarere Ausdrucksweise und ein gewisser Witz. Diese Dinge können aus meiner Erfahrung die wenigstens Sprecher,
die noch nicht lange vor Publikum sprechen. Das sieht man eher bei erfahrenen Sprechern mit mehreren Jahren Erfahrung.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In den letzten beiden Jahren war ich auf vielen Konferenzen und habe sehr viele gute Vorträge angehört. Mit der Zeit
kristallisiert sich ein Muster heraus, welche Eigenschaften ein guter Vortrag haben muss. Dabei nehme ich den Sprecher
erst einmal aus der Gleichung und fokussiere mich auf das Foliendesign, Dinge die Sprecher unbedingt tun sollten
unabhängig vom persönlichen Stil und die Struktur eines einprägsamen Vortrags.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_foliendesign&quot;&gt;Foliendesign&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Folien sind &lt;strong&gt;nicht&lt;/strong&gt; der Mittelpunkt der Präsentation. Dieser Punkt kann nicht oft genug wiederholt werden.
Die Folien sind &lt;strong&gt;nicht&lt;/strong&gt; der Mittelpunkt der Präsentation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nachdem das aus der Welt geschafft ist: Folien &lt;strong&gt;sind wichtig&lt;/strong&gt;. Sie sollten den Sprecher aber nur unterstützen
und dem Publikum einen Anhaltspunkt darüber geben, über was gerade gesprochen wird. Der größte Teil der Informationen
sollte der Sprecher liefern. Sonst wäre er überflüssig.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein sehr gutes Beispiel für minimalistische Folien gibt es von &lt;a href=&quot;https://twitter.com/drietmueller&quot;&gt;Daniel Rietmüller&lt;/a&gt;: &lt;a href=&quot;https://www.slideshare.net/drietmueller/clean-code-erfolgreich-einfhren-54875903&quot;&gt;Clean Code erfolgreich einführen&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wem das Design des obigen Vortrags etwas zu minimalistisch ist, der kann sich auch ein anderes Farbschema aussuchen.
Bei codeaffinen Sprechern ist &lt;a href=&quot;http://lab.hakim.se/reveal-js/#/&quot;&gt;reveal.js&lt;/a&gt; gerade sehr beliebt.
Jedes einzelne Farbschema ist auf maximale Lesbarkeit ausgelegt und kann durch HTML/CSS/JavaScript eigenhändig erweitert werden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zum Abschluss dieses Punktes noch ein gutes Video, in dem die Wirkung von schlechten Folien humorvoll demonstriert wird:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;880&quot; height=&quot;540&quot; src=&quot;https://www.youtube.com/embed/MjcO2ExtHso&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_vortrag&quot;&gt;Vortrag&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Zum Vortrag selbst gibt es ein paar sinnvolle Tricks, die helfen eine Verbindung zum Publikum aufzubauen. Denn die
eigentliche Aufgabe eines Sprechers, ist es ein persönliches Gespräch mit seinem Publikum zu führen und dadurch eine
Idee oder Wissen zu vermitteln.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Besten schaffen es tatsächlich, dass ich mich direkt angesprochen fühle. Dadurch kommt die Botschaft besser an.
Aus meiner Erfahrung als Vortragender waren die Situationen in denen ich am meisten positives Feedback bekommen habe,
die in denen ich mich eins mit dem Publikum gefühlt habe (obwohl der Vortrag inhaltliche Mängel hatte ;) ).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Es gibt aus meiner Sicht zwei Kernpunkte, die berücksichtigt werden sollten. Erstens spricht ein guter Sprecher mit
jedem einzelnen des Publikums. Dazu ist es wichtig, Augenkontakt aufzubauen und diesen für mindestens einen Gedankengang
zu behalten. Dann bekommt der Zuhörer das Gefühl, dass er direkt angesprochen wurde. Eine Mikrokonversation also. Wer es
als Sprecher einmal bewusst probiert hat, wird erstaunt sein, wie gut das funktioniert.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Es gibt nur ein Problem. Wie geht man bei großen Räumen vor? Das ist relativ einfach zu bewerkstelligen: Der Raum wird
in Sektoren eingeteilt und nacheinander mit der oben beschriebenen Technik abgearbeitet.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Natürlich ist so ein Vorgehen nur möglich, wenn der Vortrag sitzt, was mich zum zweiten Kernpunkt bringt. Ein guter
Vortragender weiß, was er vermitteln will. Er kann seinen Vortrag durch mindestens fünfmaliges Üben so gut, dass er
dem roten Faden folgen kann ohne nachzudenken. Das verschafft die Freiheit, die gebraucht wird, um die persönliche
Verbindung zum Publikum herzustellen!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_der_rote_faden&quot;&gt;Der rote Faden&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Es gibt viele Möglichkeiten eine Vortrag aufzubauen, über die ich in einem späteren Blog noch schreiben werde. Wichtig
bei allen ist ein erkannbarer roter Faden, um den es sich drehen sollte. Das heißt, dass der Bezug zum Grundthema für
den Zuhörer erkennbar bleiben sollte. Dabei ist das Abtauchen in etwas weiter entfernte Gedankengänge vollkommen in
Ordnung. Es sollte nur vorher gesagt werden, warum das passiert oder in einem AHA-Moment enden, der dem fragenden Publikum
eine überraschende Einsicht präsentiert. Letzteres habe ich bis jetzt selten erlebt. &lt;a href=&quot;https://twitter.com/ufried&quot;&gt;Uwe Friedrichsen&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sehr heikel sind in diesem Zusammenhang auch Live-Demos, bei denen mehrere Programme gleichzeitig geöffnet werden.
Das Springen zwischen den Fenstern verwirrt oft. IDEs sind meistens an sich schon komplex. Auf der Leinwand alles so schnell zu erfassen,
ist als Zuschauer fast unmöglich. Hier ist eine genaue Erläuterung des Vorgehens und aller relevanten Bestandteile wichtig.
Hier hilft es ungemein besonders langsam vorzugehen und die Reaktionen des Publikums zu beobachten!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mit einfachen Mitteln, die nichts mit dem persönlichen Stil zu tun haben lässt sich bei Vorträgen viel erreichen.
Achtet man bei der Erstellung der Folien auf ein klares minimalistisches Design und stellt den Sprecher in den
Vordergrund ist der Grundstein gelegt. Wird dann noch eine persönliche Verbindung mit dem Publikum hergestellt
kann die gut eingeübte und mit einem roten Faden durchzogene Präsentation nur gelingen!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Präsentation von Kevin Goldsmith ist ein Beispiel für alle Punkte, die ich aufgeführt habe:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;880&quot; height=&quot;540&quot; src=&quot;https://www.youtube.com/embed/oU3G6xAAIoo&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Quellen:
&lt;a href=&quot;http://amzn.to/2xPUpBF&quot; class=&quot;bare&quot;&gt;http://amzn.to/2xPUpBF&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Mutationstesten: Abgrenzung zu anderen Testverfahren</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/Mutationstesten_Abgrenzung_zu_anderen_Testverfahren.html</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/Mutationstesten_Abgrenzung_zu_anderen_Testverfahren.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Mutation_testing&quot;&gt;Mutationstesten&lt;/a&gt; ist ein Verfahren, um Tests
aussagekräftiger zu machen. Es ist quasi der Goldstandard unter den Testabdeckungsmetriken. Warum? Es prüft nicht nur, ob eine Zeile
Code abgedeckt wurde, sondern auch, ob der/die dazugehörige(n) Test(s) tatsächlich Fehler in dieser Zeile finden können. Dazu werden
kleine absichtlich kleine Fehler in den Code eingebaut (Mutationen), die von der Testsuite gefunden werden sollten. Wie das alles genau
aussieht, werde ich demnächst beschreiben.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Heute geht es mehr um die Platzierung von Mutationstesten im Vergleich zu anderen Testverfahren, wie zum Beispiel Unit-Tests.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_was_mutationstests_nicht_sind&quot;&gt;Was Mutationstests nicht sind&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mutationstesten testet &lt;strong&gt;nicht&lt;/strong&gt; den eigenen Sourcecode, sondern die dazugehörige &lt;strong&gt;Testsuite&lt;/strong&gt;. In meinen beiden Vorträgen über
Mutationstesten habe ich das nicht genau genug herausgearbeitet. Das hat Gründe, auf die ich in den nächsten Abschnitten eingehen werde.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_die_tests_testen&quot;&gt;Die Tests testen?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Um die Tests zu testen braucht es eine Grundvoraussetzung: &lt;a href=&quot;https://de.wikipedia.org/wiki/Testabdeckung#Testabdeckung_in_der_Softwaretechnik&quot;&gt;Testabdeckung bzw. Testüberdeckung&lt;/a&gt;.
Im Falle von Mutationstesten reicht hier die sehr einfache Metrik der &lt;a href=&quot;https://stackoverflow.com/questions/8229236/differences-between-line-and-branch-coverage&quot;&gt;Zeilenüberdeckung&lt;/a&gt; aus,
die besagt, dass die Tests dazu geführt haben, dass eine Zeile ausgeführt wurde. Erst wenn eine Zeile von mindestens einem Test ausgeführt wurde, wird sie für Mutationen in Betracht gezogen.
Ansonsten würden die Mutationen mit Sicherheit nicht von der Testsuite entdeckt werden. Dementsprechend ist die Zeilenüberdeckung mit Mutationstesten quasi &lt;strong&gt;verheiratet&lt;/strong&gt;, damit sie effektiv durchgeführt werden kann. Ansonsten würde man viele nicht auffindbare Mutationen erzeugen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Man kann Mutationstesten also als eine Art &lt;a href=&quot;https://de.wikipedia.org/wiki/Regressionstest&quot;&gt;Regressionstest&lt;/a&gt; beschreiben, das sicherstellt, dass eingebrachte Fehler in den Code von der Testsuite gefunden werden können. Es ersetzt also nicht den klassischen Unit-Test oder macht andere Testverfahren überflüssig. Viel eher ist es eine praktikable Hilfestellung, um die Qualität der Testsuite hochzuhalten.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_false_positives&quot;&gt;False Positives&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ich spreche in meinem Vortrag gerne von &lt;strong&gt;False Positives&lt;/strong&gt;. Technisch ist dieser Begriff bestimmt nicht 100 % korrekt (&lt;a href=&quot;http://www.statisticshowto.com/false-positive-definition-and-examples/&quot;&gt;Siehe hier für eine sinnvolle Erklärung&lt;/a&gt;).
Aber er beschreibt für mich den Fall, dass mein Tool ein Problem meldet, wo eigentlich keines ist. Darunter fallen:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Redundanter Code, der nichts zu Funktionalität beiträgt&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mutationen die nicht von der Testsuite gefunden werden, aber die Funktionalität nicht einschränken&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Durch die Einführung von Mutationen fallen solche Codestellen auf (durch nicht getötete Mutationen). Bei genauerer Inspektion stellt
sich dann aber heraus, dass man die entsprechenden Codezeilen entweder löschen oder eben ignorieren kann.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_was_man_nebenbei_so_findet&quot;&gt;Was man nebenbei so findet&amp;#8230;&amp;#8203;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sehr oft werden auch Mutationen nicht getötet, wenn sie auf von mir sogenannte &lt;strong&gt;subtile Bugs&lt;/strong&gt; hinweisen. Der Aufruf von einer Methode
ohne Rückgabewert (void) aber mit Seiteneffekt ist so ein Fall. Meine Testsuite muss in diesem Fall erheblichen Zusatzaufwand betreiben
(zum Beispiel mit Mocks/zusätzlichen Datenbankzugriffen), um diesen Seiteneffekt sinnvoll zu testen. Das weist für mich auf einen möglichen Designfehler hin.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein weiteres Beispiel dafür sind &lt;strong&gt;if-Abfragen&lt;/strong&gt;, deren Rumpf einen Seiteneffekt erzeugt. Hier kann durch Unachtsamkeit leicht ein Bug
eingebaut werden. Mit Mutationstesten findet man diese Stellen zielsicher und sie sollten dann nicht einfach mit einem zusätzlichen
Test vor dem Unglück bewahrt werden. Besser ist es ein Refactoring zu machen. Entweder durch explizites Ausschreiben der Bedingung
oder zum Beispiel durch die Auslagerung in eine eigene Methode.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mutationstesten härtet die eigene Testsuite auf effektive Weise. Nebenbei findet sich dabei auch noch die ein oder andere Stelle
im getesteten Code, der ein Refactoring gut tun würde.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Die Probleme mit DRY auf Modulebene</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/Die_Probleme_mit_DRY_auf_Modulebene.html</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/Die_Probleme_mit_DRY_auf_Modulebene.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das &lt;a href=&quot;https://de.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself&quot;&gt;DRY – Don&amp;#8217;t Repeat Yourself – Prinzip&lt;/a&gt; haben die meisten
Entwickler*innen als wichtiges Prinzip verinnerlicht.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Um das nüchtern festzustellen: Das Kopieren von Code an sich ist im ersten Moment schmerzlos und geht schnell.
Entwickler*innen müssen sich keine Gedanken über eine sinnvolle Abstraktion oder den Ort des Codes machen, sondern kopieren ihn sich einfach an die benötigte Stelle.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Problematisch ist das erst im Fehlerfall. Tritt ein Fehler in einem Codestück auf, das x-Mal dupliziert wurde, dann ist er in allen Duplikaten ebenfalls
zu beheben. Meistens wird dann eines davon vergessen und schon fängt man sich den gleichen Fehler an einer anderen Stelle erneut ein. Das ist für alle
Beteiligten frustrierend.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_die_pragmatische_lösung_ein_gemeinsames_modul&quot;&gt;Die pragmatische Lösung: Ein gemeinsames Modul&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Als Lösung bietet sich ein gemeinsames Modul an: Nennen wir es der Einfachheit halber &lt;strong&gt;base&lt;/strong&gt;. Dort kommt die sogenannte Basisfunktionalität hinein,
die jede Applikation braucht. Problem gelöst, wir können effizient arbeiten.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_an_der_umsetzung_hapert_es&quot;&gt;An der Umsetzung hapert es&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Idee eines Basismoduls &lt;strong&gt;base&lt;/strong&gt; klingt in der Theorie einleuchtend und für mich ist sie auch eine adäquate Lösung. Wäre da nicht das Problem der
Umsetzung. Hier gibt es mehrere Punkte, die &lt;strong&gt;base&lt;/strong&gt; zum Scheitern verurteilen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_was_ist_basisfunktionalität&quot;&gt;Was ist Basisfunktionalität&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bei einer steigenden Anzahl von Basisfunktionalitäten wird es für den einzelnen Entwickler immer schwieriger zu entscheiden, welche Funktionaliät
denn eigentlich in &lt;strong&gt;base&lt;/strong&gt; untergebracht werden soll. Gepaart mit Zeitdruck wird &lt;strong&gt;base&lt;/strong&gt; immer weiter aufgebläht. Zwangsläufig importiert damit
jede davon abhängige Applikation Funktionalität die sie nicht braucht!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Nehmen wir als Beispiel an in &lt;strong&gt;base&lt;/strong&gt; befindet sich eine Utility-Klasse, die für String-Manipulationen zuständig ist. Als weitere Funktionalität
gibt es ein ganzes Package, dass das Einlesen von CSV-Dateien ermöglicht und ein Package, dass verschiedene Formate exportieren kann.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Braucht jede Applikation die Exportfunktionalität oder das Einlesen von CSV-Dateien? Sicherlich nicht! Aber wenn die Fähigkeiten zur
String-Manipulation in &lt;strong&gt;base&lt;/strong&gt; liegen und das Modul deswegen importiert, kriegt man das im Schlepptau mit. Hier besteht eine unnötige Kopplung.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;_abhängigkeit_führt_zu_nicht_evolvierbarkeit&quot;&gt;Abhängigkeit führt zu Nicht-Evolvierbarkeit&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Spinnen wir das Gedankenspiel noch etwas weiter und fügen noch einige Applikationen hinzu, am besten noch mit unterschiedlichen Java-Versionen.
So bekommt man einen schönen Baum mit &lt;strong&gt;base&lt;/strong&gt; als Wurzel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Benötigt man neue Funktionalität in &lt;strong&gt;base&lt;/strong&gt;, da irgendwer meint sie ist eine Basisfunktionalität, dann muss sich &lt;strong&gt;base&lt;/strong&gt; ändern. Idealerweise
erledigt man das auf einem Feature Branch und macht anschließend einen Merge. In der Realität entfällt dieser Merge manchmal und der Branch
entwickelt sich autonom weiter. Vielleicht sind auch schon neue Features aus einer höheren Sprachversion ausversehen verwendet worden. Das
Ergebnis sind zwei ähnliche &lt;strong&gt;base&lt;/strong&gt;-Varianten, die man nicht mehr Mergen kann.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ich höre gerade die Zweifler: Das kann doch nicht passieren, wenn man sich an das richtige Vorgehen hält!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Denen gebe ich absolut recht. Zum Beispiel kann man die Java-Version mit Maven festsetzen oder vor der Auslieferung einen Merge auf &lt;strong&gt;master&lt;/strong&gt;
fordern, keine Frage. Aber wie oft steht man unter Zeitdruck, oder die Tools versagen und dann ist es doch passiert?
Und ist es in Produktion, dann muss man plötzlich doch eine Kopie pflegen, inklusive aller Bugs, die sich darin verstecken :( .&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_mehrere_utility_module&quot;&gt;Mehrere Utility-Module&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Lösung der oben beschriebenen Probleme liegt in der Zerlegung von &lt;strong&gt;base&lt;/strong&gt; in spezialisierte Module. So kann jede Applikation
selbst entscheiden, welche Basisfunktionalität sie wirklich braucht.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ob man das so weit treiben will, wie bei &lt;a href=&quot;https://comlounge.net/npm-left-pad-javascript-markenstreit/&quot;&gt;node.js und left-pad&lt;/a&gt; lasse ich mal dahingestellt. Ich bin aber durchaus für die Linux-Philosophie &lt;a href=&quot;https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well&quot;&gt;Do one thing and do it well&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Es gibt einfach keinen Grund in seinem Modul unnötigen Code mitzuschleppen. Dieser trägt im besten Fall dazu bei, dass das API des Moduls
schwieriger zu verstehen ist, da es zu viele Belange abdeckt. Im schlechtesten Fall führt es dazu, dass man Applikationen neu ausliefern muss,
da genau dieser Code einen kritischen Bug (Sicherheitslücken!) aufweist und deswegen gepatcht werden muss.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Hier kann man schön einen Kreis zum &lt;a href=&quot;http://clean-code-developer.de/weitere-infos/solid/&quot;&gt;Single Responsibility Prinzip (SRP)&lt;/a&gt; ziehen. Nach diesem soll es nur einen Grund geben dürfen, damit sich eine Klasse ändert. Überträgt man dieses Prinzip auf die Modulebene, dann landet man zwangsläufig bei kleinen spezialisierten Modulen.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein gemeinsames &lt;strong&gt;base&lt;/strong&gt;-Modul ist in der Theorie eine pragmatische Lösung, um Basisfunktionalität an einem zentralen Ort zu pflegen.
In der Praxis führt es aber eher zu einem aufgeblähtem Modul, dass als Sammelbecken für alles Mögliche herhalten muss. Durch ungewolltes
Kopieren der Codebase, zum Beispiel mit einem nicht gemergten Feature Branch, holt man sich viele Probleme ins Boot. Vor allem
Codeduplikation inklusive aller Bugs und Updatezwang aller Applikationen bei kritischen Bugs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wesentlich sinnvoller ist eine Aufteilung der Basisfunktionalität in spezialisiertere Module. Applikationen können sich gezielt
davon bedienen und die Module wachsen nicht unkontrolliert an. Die Wahrscheinlichkeit für Codeduplikation sinkt.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Das Ziel von Mutationstesten</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/Das_Ziel_von_Mutationstesten.html</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/Das_Ziel_von_Mutationstesten.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mit das Interessanteste an einem Vortrag sind die anschließenden Fragen. Beim letzten Mal hatte ich das Gefühl die Fragen zum
&lt;a href=&quot;http://www.elektronikpraxis.vogel.de/themen/embeddedsoftwareengineering/testinstallation/articles/365764/&quot;&gt;Mutationstesten&lt;/a&gt; nicht zufriedenstellend beantwortet zu haben. Deswegen versuche ich das, in den nächsten Blogs nachzuholen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die ersten beiden Fragen waren:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Kann durch eine Mutation nicht etwas Gutes entstehen?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Was passiert, wenn sich zwei Mutationen gegenseitig ausschalten?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_gutes_durch_mutationen&quot;&gt;Gutes durch Mutationen?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mutationstesten führt Änderungen in den Sourcecode ein, die syntaktisch korrekt sind. Diese Änderungen verändern jedoch die
Semantik der Codebasis auf jeweils kleine Weise. Danach wird für jede einzelne Mutante überprüft, ob ein Test die Änderung bemerkt.
Die Tests dienen praktisch als Spezifikation, wie sich die Codebasis verhalten soll. Eine Abweichung davon ist meiner Meinung
nach immer eine Regression und damit als Fehler einzustufen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im besten Fall kann eine Mutante also nur dazu führen, dass kein Test fehlschlägt. Ob das gut oder schlecht ist, lässt sich
nur durch eine genaue Betrachtung herausfinden. Es gibt dabei zwei Möglichkeiten. Die Mutante ist tatsächlich gutmütig und
führt nicht zu falschem Programmverhalten. Das tritt tatsächlich auf, was ich in der Livedemo meines Vortrages immer zeige.
(&lt;a href=&quot;https://github.com/JohannesDienst/BOBKonf2017/tree/master/pit_demo_workspace/mutation&quot;&gt;Workspace dazu gibt es auf github&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Schlägt kein Test fehl, dann kann das auch heißen, dass meine Testsuite für diese Mutation blind ist. Das ist aus meiner Sicht
der Normalfall und sollte deshalb behoben werden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ansonsten schlägt ein Test fehl und der Sourcecode verhält sich an dieser Stelle nicht wie von den Tests gefordert.
Das würde ich als definitiven Fehler einstufen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Durch Mutationen kann nichts Gutes entstehen! Sie können nur gutmütig, also nicht Semantik verändernd sein!&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_gegenseitiges_ausschalten&quot;&gt;Gegenseitiges Ausschalten&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Können sich zwei Mutationen gegenseitig ausschalten? So wie zwei Fehler sich gegenseitig aufheben können?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;An dieser Stelle kommt ein &lt;strong&gt;Nein&lt;/strong&gt;. Die Frage kam auf, da ich im Pecha Kucha Vortrag nicht genug Zeit und Präzision hatte, den
genauen Ablauf eines Mutationstests zu verdeutlichen. Ich hole das hiermit nach:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Zuerst werden Mutanten aus dem Sourcecode erstellt&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Jede Mutante enthält &lt;strong&gt;eine einzige&lt;/strong&gt; Veränderung, der restliche Sourcecode wird nicht verändert&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Jede einzelne Mutante enthält den gesamten Sourcecode (Es handelt sich also um eine Kopie mit der einen Änderung)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alle Tests werden auf jeder einzelnen Mutante ausgeführt&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Schlägt mindestens ein Test fehl bei einer Mutante, dann gilt sie als getötet&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Rein vom Ablauf her ist es also nicht möglich, dass sich Mutanten gegenseitig aufheben.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mutationstesten so zu erklären, dass das Vorgehen verständlich ist, ist schwierig. Durch diesen Beitrag habe ich gezeigt,
dass aus Mutationen im besten Fall nichts Schlechtes entstehen kann. Außerdem wurde erklärt, dass sich Mutanten, aufgrund
des Ablaufs des Mutationstestens, nicht gegenseitig aufheben können.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In den nächsten Beiträgen mache ich zuerst einen Ausflug in Überdeckungsmaße. Die Frage die ich abschließend klären will
lautet: Führt eine hohe Abdeckung bei diesen Maßen bereits zu einer deutlich besseren Mutationsabdeckung.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Code Coverage am Beispiel Zweigüberdeckungs Branch Coverage</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/Code_Coverage_am_Beispiel_Zweigueberdeckungs_Branch_Coverage.html</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/Code_Coverage_am_Beispiel_Zweigueberdeckungs_Branch_Coverage.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Im letzten &lt;a href=&quot;/blog/2019/Code_Coverage+am_Beispiel_Zeilenueberdeckung_Line_Coverage.html&quot;&gt;Blog&lt;/a&gt; ging es um Zeilenüberdeckung.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ich habe gezeigt, wie man sie am Beispiel des &lt;a href=&quot;https://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens&quot;&gt;Game of Life von Conway&lt;/a&gt; einsetzt,
um bessere Tests zu schreiben, die jede Anweisung mindestens einmal ausführen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In diesem Teil möchte ich zuerst zeigen, warum die Zeilenüberdeckung zwar eine sinnvolle Metrik ist, aber doch nicht ausreicht,
um die Qualität der Testsuite abzusichern. Das lässt sich sehr leicht an einem Fehler zeigen, den die bisherigen Tests nicht gefunden haben.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Als Zweites möchte ich auf die Zweigüberdeckung eingehen. Diese ist eine echte Obermenge der Zeilenüberdeckung und umfasst die
Zeilenüberdeckung damit vollständig. Darüber hinaus wird mit einer vollständigen Zweigüberdeckung erreicht, dass jeder mögliche Zweig
bei der Ausführung einer Codebasis von den Tests mindestens einmal durchlaufen wird.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_zeilenüberdeckung_unzureichend&quot;&gt;Zeilenüberdeckung unzureichend&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die bis jetzt implementierte Testsuite aus dem letzten Blog hat eine Zeilenüberdekcung von 100% erreicht. Dieser Wert täuscht darüber hinweg,
dass die Testsuite nicht ausreichend ist.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Betrachten wir den Konstruktor genauer:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;public Cell(int neighborCount) {
  neighbors = new Cell[neighborCount];
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Hier versteckt sich eine &lt;strong&gt;java.lang.NegativeArraySizeException&lt;/strong&gt;. Sie tritt auf, wenn ein negativer Integer übergeben wird.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das ein solcher Fehler nicht von der Testsuite abgedeckt wird, ist nicht verwunderlich. Aus eigener Erfahrung weiß ich,
dass man Tests gerne für den positiven Fall schreibt. Der negative Fall wird aus Unachtsamkeit oder Faulheit weggelassen.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_zweigüberdeckung_verschärfte_zeilenüberdeckung&quot;&gt;Zweigüberdeckung: Verschärfte Zeilenüberdeckung&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Zweigüberdeckung fordert, dass ein Zweig der Codebasis mindestens einmal durchlaufen wird. Damit subsumiert sie die
Zeilenüberdeckung und ist ein leistungsfähigeres Maß. Eine Testsuite mit vollständiger Zweigüberdeckung stellt sicher,
dass jeder Zweig der Codebasis einmal durchlaufen wurde. Gibt es keine Bedingungen oder Schleifen, dann entspricht sie praktisch der Zeilenüberdeckung.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bei Bedingungen müssen die Tests sicherstellen, dass der Wert der Bedingung einmal &lt;strong&gt;true&lt;/strong&gt; und einmal &lt;strong&gt;false&lt;/strong&gt; wird.
Ebenso bei Schleifen. Was zur Folge hat, dass die Schleife nicht mehr als zweimal durchlaufen werden muss, um die Zweigüberdeckung zu garantieren.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Gibt es jedoch komplexere Abhängigkeiten im Programmablauf, dann können Sie ungetestet bleiben. Wie das genau aussieht,
zeige ich an der Methode &lt;strong&gt;isAliveInNextGeneration()&lt;/strong&gt; der Klasse &lt;strong&gt;Cell&lt;/strong&gt;. Hier ist sie noch einmal:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;public boolean isAliveInNextGeneration() {
  int livingNeighbors = 0;
  for (Cell cell : neighbors) {
    if (cell.isAlive()) {
      livingNeighbors++;
    }
  }

  if (!isAlive &amp;amp;amp;&amp;amp;amp; livingNeighbors == 3) {
    return true;
  }
  else if (isAlive &amp;amp;amp;&amp;amp;amp; livingNeighbors &amp;amp;lt;= 3) {
    return true;
  }

  return false;
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Unsere Testsuite erreicht für die Zweigüberdeckung folgendes Ergebnis:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;link:http://johannesdienst.net/wp-content/uploads/2017/08/BranchCoverage_isAliveNextGeneration_initial.png&quot;&amp;gt;&amp;lt;img src=&quot;http://johannesdienst.net/wp-content/uploads/2017/08/BranchCoverage_isAliveNextGeneration_initial.png&quot; alt=&quot;BranchCoverage_isAliveNextGeneration_initial&quot; width=&quot;1051&quot; height=&quot;704&quot; class=&quot;aligncenter size-full wp-image-887&quot; /&amp;gt;]&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In Zeile 27 und 28 wurden jeweils beide Branches durchlaufen. Da liegt daran, dass wir in den Tests ein Cell-Array mit lebenden und nicht lebenden Cell-Objekten übergeben haben.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Interessanter wird es da in Zeile 33. Nur einer von vier Branches wurde abgedeckt. Selbiges in Zeile 36. Reduzieren wir &lt;strong&gt;!isAlive&lt;/strong&gt; und &lt;strong&gt;livingNeighbors == 3&lt;/strong&gt; der ersten Bedingung auf zwei Booleans, dann ergibt sich eine Wahrheitstabelle:&lt;/p&gt;
&lt;/div&gt;
&lt;table class=&quot;tableblock frame-all grid-all stretch&quot;&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%;&quot;&gt;
&lt;col style=&quot;width: 50%;&quot;&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;!isAlive&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;livingNeighbors == 3&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;----------&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;--------------------&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;true&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;true&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;true&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;false&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;false&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;false&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;false&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;true&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Fälle 1, 3 und 4 sind bereits durch die Testsuite abgedeckt. Für den zweiten Fall soll die Testsuite um einen Test erweitert werden. Eine tote Zelle mit sieben lebenden Nachbarn ist in der nächsten Generation immer noch tot:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;@Test
public void setSevenLivingNeighbors_IsDead_IsDeadInNextGeneration() {
  Cell cell = getCell(false, 8);
  Cell[] neighbors = new Cell[8];
  for (int i = 0; i &amp;amp;lt; 8; i++) {
    if (i &amp;amp;lt; 7) {
      neighbors[i] = getCell(true, 8);
    }
    else {
      neighbors[i] = getCell(false, 8);
    }
  }
  cell.setNeighbors(neighbors);
  assertFalse(&quot;Cell should be dead with seven living neighbors&quot;, cell.isAliveInNextGeneration());
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mit diesem Test ergibt die Zweigabdeckung:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2019/BranchCoverage_isAliveNextGeneration_complete.png&quot; alt=&quot;BranchCoverage der isAliveNextGeneration_complete&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Interessanterweise führt dieser eine Test dazu, dass auch in Zeile 36 die Zweigüberdeckung vollständig ist. Das liegt an den Bedingungen selbst. Die Wahrheitstabellen bestätigen dies. Das Aufstellen überlasse ich aber dem geneigten Leser :-)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Der ergänzte Test ist meiner Meinung nach wichtig, da er einen negativen Fall abdeckt, der in der ursprünglichen Testsuite gefehlt hat.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Zeilenüberdeckung findet nicht unbedingt Fehler. Sind die Tests nicht sinnvoll geschrieben oder decken nur den Positivfall ab, dann läuft man Gefahr sich in falscher Sicherheit zu wiegen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Auch eine vollständige Zweigüberdeckung hilft an dieser Stelle nicht weiter. Auch wenn sie als Obermenge der Zeilenüberdeckung noch umfangreichere Tests fordert. Sie fordert aber, dass Bedingungen sowohl mit dem Wert &lt;strong&gt;true&lt;/strong&gt; als auch &lt;strong&gt;false&lt;/strong&gt; durchlaufen werden. Durch sie konnte ein fehlender Test ergänzt werden, der ansonsten nicht getestet worden wäre.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Da sie nur Zweige betrachtet ist sie aber nicht so leistungsfähig wie die Pfadüberdeckung, die alle möglichen Pfade in der Codebasis abdeckt. Um dieses Thema geht es im nächsten Blogpost.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Links:
&lt;a href=&quot;/blog/2019/Code_Coverage+am_Beispiel_Zeilenueberdeckung_Line_Coverage.html&quot;&gt;Teil 1 Zeilenüberdeckung&lt;/a&gt;
&lt;a href=&quot;https://de.wikipedia.org/wiki/Kontrollflussorientierte_Testverfahren#Pfad.C3.BCberdeckungstest&quot;&gt;Kontrollflussorientierte Testverfahren bei Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Code Coverage am Beispiel: Pfadüberdeckung (Path Coverage)</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/Code_Coverage_am_Beispiel_Pfadueberdeckung_Path_Coverage.html</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/Code_Coverage_am_Beispiel_Pfadueberdeckung_Path_Coverage.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In den letzten beiden Blogposts ging es um die Überdeckungsmaße &lt;a href=&quot;/blog/2019/Code_Coverage_am_Beispiel_Zweigueberdeckungs_Branch_Coverage.html&quot;&gt;Zweigüberdeckung&lt;/a&gt; &lt;a href=&quot;/blog/2019/Code_Coverage+am_Beispiel_Zeilenueberdeckung_Line_Coverage.html&quot;&gt;Zeilenüberdeckung&lt;/a&gt;.
Die Zweigüberdeckung ist ein stärkeres Maß für die Qualität der Abdeckung, da sie die Zeilenüberdeckung enthält.
Sie ist also eine echte Obermenge.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Pfadüberdeckung ist wiederum eine echte Obermenge der Zweigüberdeckung und ist damit als das härteste Maß der Überdeckungsmessung zu betrachten.
In diesem Post wird zuerst wieder an einem Beispiel die Pfadüberdeckung vorgestellt. Ziel ist es, eine vollständige Pfadüberdeckung durch die
vorhandene Testsuite zu erreichen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Auf los geht&amp;#8217;s los :)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_pfadüberdeckung_die_theorie_vollständig&quot;&gt;Pfadüberdeckung die Theorie: Vollständig&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Pfadüberdeckung kommt in mehreren Varianten vor. Zuerst soll jedoch die vollständige Pfadüberdeckung erläutert werden. Nehmen
wir uns dazu eine einfache Methode als Beispiel (Achtung: &lt;strong&gt;kein&lt;/strong&gt; sinnvolles Beispiel!):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;exampleblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;public int doSomething(int max) {
  int temp = max;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;literalblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;if (max &amp;amp;lt; 0) {
  return -1;
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;literalblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;if (max == 0) {
  temp = Integer.MAX_VALUE;
} else {
  return temp;
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;literalblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;  return temp;
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Um alle Pfade zu entdecken, lohnt es sich einen sogenannten &lt;a href=&quot;https://de.wikipedia.org/wiki/Kontrollflussgraph&quot;&gt;Kontrollflussgraphen&lt;/a&gt; zu erstellen:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2019/Path_Coverage_Simple_Example.png&quot; alt=&quot;Path_Coverage_Simple_Example&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wie man sieht, gibt es selbst in dieser einfachen Methode drei Pfade, die durch separate Tests abgedeckt werden müssen.
Überträgt man das auf eine größere Codebasis, dann gibt es eine unendliche Anzahl von Pfaden.
Eine vollständige Pfadabdeckung ist also nicht praktisch umsetzbar!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_pfadüberdeckung_die_theorie_c2b_und_c2c_schleifen_begrenzen&quot;&gt;Pfadüberdeckung die Theorie: C2b und C2c &amp;#8594; Schleifen begrenzen&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Eine Sache, die in der vorherigen Methode bewusst ausgespart wurde, sind Schleifen. Diese führen zu potenziell
unendlich vielen Pfaden, da jeder Schleifendurchlauf jeweils als eigener Pfad gezählt werden muss. Kombiniert mit
weiteren Anweisungen in der Methode explodiert die Pfadanzahl buchstäblich.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dafür gibt es die eingeschränkten Methoden der Pfadüberdeckungsmessung C2b und C2c. Bei C2b wird die Anzahl der
Schleifendurchläufe auf zwei reduziert. Bei C2c auf eine natürliche Zahl &lt;strong&gt;n&lt;/strong&gt;. Damit bekommt man die ausufernde Anzahl der Pfade in den Griff!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_methode_vollständig_abdecken&quot;&gt;Methode vollständig abdecken&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Für die Methode &lt;strong&gt;isAliveInNextGeneration()&lt;/strong&gt; soll nun eine C2b-Abdeckung hergestellt werden. Hier noch einmal die Methode:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;public boolean isAliveInNextGeneration() {
  int livingNeighbors = 0;
  for (Cell cell : neighbors) {
    if (cell.isAlive()) {
      livingNeighbors++;
    }
  }

  if (!isAlive &amp;amp;amp;&amp;amp;amp; livingNeighbors == 3) {
    return true;
  }
  else if (isAlive &amp;amp;amp;&amp;amp;amp; livingNeighbors &amp;amp;lt;= 3) {
    return true;
  }

  return false;
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Der Kontrollflussgraph ist ziemlich komplex:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2019/Path_Coverage_Complex_Example.png&quot; alt=&quot;Path_Coverage_Complex_Example&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Bei meiner Zählung bekomme ich folgende Pfadanzahl, wenn ich für die For-Schleife drei Pfade annehme:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Erstes IF Then: 3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Zweites IF Then: 3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Zweites IF Else: 3&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das wären dann &lt;strong&gt;neun&lt;/strong&gt; Testfälle für diese Methode. Meiner Meinung nach ist das noch zu schaffen. Außerdem ist dann
wirklich jeder Pfad abgedeckt, den der Programmablauf nehmen kann.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Dieses reale Beispiel zeigt, dass die Pfadüberdeckung sinnvoll ist. Praktikabel ist sie deswegen aber noch lange
nicht. Die Explosion der Testfälle ist wahrscheinlich in keinem Projekt akzeptabel.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Noch interessanter ist, dass bei meinen Recherchen zu einem Tool für die Messung der Pfadüberdeckung keines zu
finden war. Anscheinend hat dieses Maß keine Praxisrelevanz ;) .&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die vollständige Pfadüberdeckung ist bei einfachen Methoden leicht zu erreichen. Bei komplexeren Methoden
artet es schnell in viel Arbeit aus. Als Abhilfe können eingeschränkte Versionen der Pfadüberdeckung genutzt
werden (C2b oder C2c), die aber ebenfalls viele Testfälle erfordern.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein weiteres Problem sind nicht beschreitbare Pfade, da sich die Vorbedingungen nicht in der benötigten
Kombination herstellen lassen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Trotzdem ist es ein nützliches Werkzeug, besonders bei kritischen Pfaden, da eine vollständige Abdeckung
aller Programmabläufe sichergestellt ist!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Code Coverage am Beispiel: Zeilenüberdeckung (Line Coverage)</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/Code_Coverage+am_Beispiel_Zeilenueberdeckung_Line_Coverage.html</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/Code_Coverage+am_Beispiel_Zeilenueberdeckung_Line_Coverage.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wie letzte Woche angekündigt, werde ich diese Woche beginnen, die verschiedenen Überdeckungsmaße für Code vorzustellen.
Als Beispielprojekt habe ich mir das &lt;a href=&quot;https://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens&quot;&gt;Game of Life von Conway&lt;/a&gt;
ausgesucht, was als interessante Übungsaufgabe Einiges an Logik hergibt.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_eine_einfache_zelle&quot;&gt;Eine einfache Zelle&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Regeln für Conways Game of Life sind sehr einfach:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Eine tote Zelle wird in der nächsten Generation belebt, wenn sie genau drei lebende Nachbarzellen hat&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Eine lebende Zelle lebt in der nächsten Generation weiter, wenn sie genau drei oder weniger als drei lebende Nachbarzellen besitzt&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Eine lebende Zelle stirbt in der nächsten Generation, wenn sie mehr als drei lebende Nachbarn besitzt (Überbevölkerung und so ;-) )&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mit diesen Vorgaben habe ich eine einfach Klasse implementiert. Manche Methoden der Klasse sind zur besseren Testbarkeit eingeführt worden:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;package jdienst.basic;

public class Cell {

  private boolean isAlive = false;
  private Cell[] neighbors;

  public Cell(int neighborCount) {
    neighbors = new Cell[neighborCount];
  }

  public boolean isAlive() {
    return isAlive;
  }

  public void enlive() {
    isAlive = true;
  }

  public Cell setNeighbors(Cell[] neighbors) {
    this.neighbors = neighbors;
    return this;
  }

  public boolean isAliveInNextGeneration() {
    int livingNeighbors = 0;
    for (Cell cell : neighbors) {
      if (cell.isAlive()) {
        livingNeighbors++;
      }
    }

    if (!isAlive &amp;amp;amp;&amp;amp;amp; livingNeighbors == 3) {
      return true;
    }
    else if (isAlive &amp;amp;amp;&amp;amp;amp; livingNeighbors &amp;amp;lt;= 3) {
      return true;
    }

    return false;
  }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_zeilenüberdeckung_abdeckung&quot;&gt;Zeilenüberdeckung/-abdeckung&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das Ganze habe ich testgetrieben entwickelt. Am Ende ist eine Testsuite von vier Tests entstanden, die auf den ersten Blick
hinreichend gut aussieht. Leider kann man sich darauf nicht verlassen. Deswegen gibt es die Möglichkeit die Tests mit
Testabdeckungsmaßen zu überprüfen.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das einfachste dieser Maße ist die Zeilenüberdeckung/-abdeckung, sie gibt an, ob eine bestimmte Codezeile überhaupt von
den Tests ausgeführt wird. Dieses Verfahren zeigt also an, welche Abschnitte der Codebasis &lt;strong&gt;nicht&lt;/strong&gt; von der Testsuite ausgeführt werden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Daraus folgt, dass Fehler, die sich in diesen Bereichen verstecken, nicht gefunden werden können. Deswegen sollte als
Faustregel als Ziel immer eine Abdeckung zu 100 % stehen. Wenigstens bei Code, der Logik enthält. Eine vollständige Abdeckung
in der gesamten Codebasis ist nicht effizient umsetzbar und deswegen unwirtschaftlich.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_testsuite_bewerten&quot;&gt;Testsuite bewerten&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;An dieser Stelle zeige ich die ersten beiden Tests. Den Rest kann man in meinem &lt;a href=&quot;https://github.com/JohannesDienst/Mutationtesting_Showcase&quot;&gt;Repository auf Github&lt;/a&gt; finden.
Das Projekt inklusive Konfiguration für alle Tools wurde mit Maven angelegt. Mit &lt;strong&gt;mvn clean package site:site&lt;/strong&gt; löst man das Reporting aus. Unter &lt;strong&gt;target/site/project-reports.html&lt;/strong&gt; kann der Report für die Zeilenüberdeckung angezeigt werden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Hier nun endlich die Tests:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;@Test
public void shouldBeDeadAfterConstruction() {
  Cell cell = new Cell(8);
  assertFalse(&quot;Cell is alive. But it should not be alive after construction&quot;, cell.isAlive());
}

@Test
public void setThreeLivingNeighbors_IsDead_IsAliveInNextGeneration() {
  Cell cell = getCell(false, 8);
  Cell[] neighbors = new Cell[8];
  for (int i = 0; i &amp;amp;lt; 8; i++) {
     if (i &amp;amp;lt; 3) {
      neighbors[i] = getCell(true, 8);
    }
    else {
      neighbors[i] = getCell(false, 8);
    }
  }
  cell.setNeighbors(neighbors);
  assertTrue(&quot;Cell should be alive with three living neighbors&quot;, cell.isAliveInNextGeneration());
}

public void setThreeLivingNeighbors_IsAlive_IsAliveNextGeneration() { /* ... */ }

public void setEightLivingNeighbors_IsAlive_IsDeadNextGeneration() { /* ... */ }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Wie man sieht, reichen die Tests aus, um sicherzustellen, dass jede Zeile Code mindestens einmal von den Tests ausgeführt wird.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2019/LinecoverageCell.png&quot; alt=&quot;Line Coverage der Zelle Überblick&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ein genauerer Blick verrät uns jedoch, dass das Tool noch Verbesserungsvorschläge in der Verzweigungsüberdeckung (Branch Coverage) hat.
Die Detailansicht gibt Aufschluss darüber, an welchen Stellen es hakt. Darum kümmern wir uns nächste Woche.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;../../images/blog/2019/LineCoverageCell2.png&quot; alt=&quot;Line Coverage der Zelle im Detail&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Zeilenüberdeckung/-abdeckung ist das einfachste Überdeckungsmaß. Mit diesem kann festgestellt werden, an welcher Stelle die
Tests noch ausgebaut werden müssen, damit jede Zeile der Codebasis von den Tests ausgeführt wird. Leider trifft es keine Aussage
darüber, ob die Tests auf irgendeine Weise sinnvoll sind.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Welche Fehler es noch in der Cell-Klasse gibt und wie die Qualität der Tests durch Verzweigungsüberdeckung gesteigert werden kann,
wird im nächsten Blog gezeigt. Bis dahin: Happy Testing!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>Buchrezension Basiswissen für Softwarearchitekten 3 Auflage</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/Buchrezension_Basiswissen_fuer_Softwarearchitekten_3_Auflage.html</link>
      <pubDate>Sat, 27 Jul 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/Buchrezension_Basiswissen_fuer_Softwarearchitekten_3_Auflage.html</guid>
      <description>
      &lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Das Buch soll als Vorbereitung für die Prüfung zum iSAQB Certified Professional for Software Architecture Foundation Level dienen.
Dazu soll es auf dem aufbauend auf dem Lehrplan alles notwendige Wissen enthalten, das zum Bestehen der Prüfung notwendig ist.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_aufbau&quot;&gt;Aufbau&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Die Kapitel sind in sich abgeschlossen und beinhalten zu Anfang immer Lernziele, die direkt aus dem Lehrplan entnommen sind.
Zum Ende eines jeden Kapitels befindet sich eine Lernkontrolle, die die Punkte aus dem Lehrplan aufgreifen, die in dem jeweiligen
Kapitel vermittelt worden sind. Für die Prüfung relevant sind die Kapitel 2-5: Grundlagen von Softwarearchitekturen, Entwurf von
Softwarearchitekturen, Beschreibung und Kommunikation von Softwarearchitekturen und Softwarearchitekturen und Qualität.
Abgerundet wird das Buch von einem umfangreichen Anhang, der acht Beispielfragen, ein Abkürzungsverzeichnis, ein Glossar und
ein umfangreiches Literaturverzeichnis enthält.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_inhalt&quot;&gt;Inhalt&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Der Inhalt des Buches ist leider nicht aufeinander aufgebaut. Jedes Kapitel steht für sich. Die Darstellung der einzelnen Lehrinhalte
wirkt an vielen Stellen sehr knapp, sodass man unbedingt weiter in der verwiesenen Literatur recherchieren sollte. Studiert man
den Lehrplan für die Zertifizierung, dann fällt auf, dass teilweise die Lerninhalte aus der Lernkontrolle nur angerissen wurden,
oder gar nicht behandelt wurden.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_bewertung&quot;&gt;Bewertung&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ich habe zusätzlich zum Buch eine 4-tägige Schulung besucht. Diese war um einiges umfangreicher, obwohl sie sich ebenfalls direkt
am Lehrplan orientiert. Von einem Buch zur Prüfungsvorbereitung hatte ich mir ehrlich gesagt das gleiche gewünscht. Dass man die
Beispielfragen aus dem Anhang nicht mithilfe des Buches (oder nur sehr schwer, da im Inhaltsverzeichnis nicht ausgewiesen) beantworten
kann, hinterlässt einen fahlen Beigeschmack. Das Buch wirkt an vielen Stellen zu knapp. Die besprochenen Dinge sind aber gut
aufbereitet und graphisch anschaulich dargestellt. Zu loben sind die zahlreichen Literaturverweise, die unbedingt zum Selbststudium
herangezogen werden sollten.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;_fazit&quot;&gt;Fazit&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ich kann dieses Buch bedingt weiterempfehlen. Wenn der Schreibstil etwas flüssiger wäre, dann könnte es als guter Einstieg dienen.
Leider habe ich keinen wirklichen Zugang zu diesem Buch gefunden.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
	  </description>
    </item>
    
    <item>
      <title>My Shell-Config on Windows 10</title>
      <link>https://fiveandahalfstars.ninja/blog/2019/2019-04-01-shell-config.html</link>
      <pubDate>Mon, 1 Apr 2019 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2019/2019-04-01-shell-config.html</guid>
      <description>
      &lt;p&gt;Windows 10 together with the Windows Subsystem for Linux (WSL) is now a great OS for development.&lt;br /&gt;
You can easily switch between the powershell and bash and thus test your code on both systems.&lt;/p&gt;
&lt;p&gt;What I love in powershell is the ability to start the windows explorer in the current directory with &lt;code&gt;ii .&lt;/code&gt;.&lt;br /&gt;
You standard bash does not have this feature out of the box (it doesn&apos;t know about windows) but you can configure an alias for that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alias ii=&apos;powershell.exe ii&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works because out of the box, you can use windows commands within your linux running in WSL!&lt;/p&gt;
&lt;p&gt;I also love to be able to view each file in its corresponding standard app by just typing &lt;code&gt;start &amp;lt;filename&amp;gt;&lt;/code&gt;.&lt;br /&gt;
So &lt;code&gt;start index.html&lt;/code&gt; will open the &lt;code&gt;index.html&lt;/code&gt; from the current folder in chrome.&lt;br /&gt;
Again, an alias will add this feature to your bash:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alias start=&apos;cmd.exe /c start&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cool, isn&apos;t it?&lt;/p&gt;
&lt;p&gt;How about beeing able to run graphical tool on WSL?&lt;br /&gt;
Just add&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export DISPLAY=127.0.0.1:0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to your &lt;code&gt;~/.bashrc&lt;/code&gt; and start an XServer on your windows machine (I use VcXsrv) and many linux apps will run on Windows within WSL.&lt;/p&gt;
&lt;p&gt;Note: This feature is still unsupported and you will et some error messages on the terminal&lt;br /&gt;
You might want to use WLinux from the Microsoft Store to minimize these problems.&lt;br /&gt;
WLinux is a Linunx optimized for WSL.&lt;br /&gt;
It is even pre-configured to easily connect to your windows docker host wihtout having to deactivate security.&lt;/p&gt;
&lt;p&gt;Often it is annoying when the prompt shows you the whole path like &lt;code&gt;mnt/c/Users/yourname/projects/yourproject/etc&lt;/code&gt;.&lt;br /&gt;
Fix this by replacing the prompt setting in your &lt;code&gt;~/.bashrc&lt;/code&gt; with this line:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;if [ &amp;quot;$color_prompt&amp;quot; = yes ]; then
    PS1=&apos;\[\e[32m\]\u\[\e[m\]:\[\e[33m\]${PWD#&amp;quot;${PWD%/*/*}/&amp;quot;}\[\e[m\]\$ &apos;
else
    PS1=&apos;${debian_chroot:+($debian_chroot)}\u@\h:\w\$ &apos;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It will only display your user name and the last two folders of your current directory.&lt;/p&gt;
&lt;p&gt;You can do the same for powershell by adding the following to your profile:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function prompt {
    $dateTime = get-date -Format &amp;quot;dd.MM.yyyy HH:mm:ss&amp;quot;
    $currentDirectory = $(Get-Location)
    $UncRoot = $currentDirectory.Drive.DisplayRoot

    write-host &amp;quot;PS $(Split-Path -Leaf $pwd)&amp;gt;&amp;quot; -NoNewline -ForegroundColor Yellow
    return &amp;quot; &amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To check where you profile is located, just type &lt;code&gt;$profile&lt;/code&gt; at the prompt.&lt;br /&gt;
It is very likely that it is currently an empty file.&lt;/p&gt;
&lt;p&gt;And while you edit your profile, you might also want to add these lines:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$console = $host.ui.rawui
$console.backgroundcolor = &amp;quot;black&amp;quot;
$console.foregroundcolor = &amp;quot;white&amp;quot;
$colors = $host.privatedata
$colors.verbosebackgroundcolor = &amp;quot;Magenta&amp;quot;
$colors.verboseforegroundcolor = &amp;quot;Green&amp;quot;
$colors.warningbackgroundcolor = &amp;quot;Red&amp;quot;
$colors.warningforegroundcolor = &amp;quot;white&amp;quot;
$colors.ErrorBackgroundColor = &amp;quot;DarkCyan&amp;quot;
$colors.ErrorForegroundColor = &amp;quot;Yellow&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These will fix the standard-colors which make some shell output unreadable.&lt;/p&gt;
&lt;p&gt;What are your tricks?&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>The Results are in!</title>
      <link>https://fiveandahalfstars.ninja/blog/2018/2018-11-02-hacktoberfest.html</link>
      <pubDate>Fri, 2 Nov 2018 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2018/2018-11-02-hacktoberfest.html</guid>
      <description>
      &lt;p&gt;&lt;a href=&quot;https://hacktoberfest.digitalocean.com&quot;&gt;Hacktoberfest&lt;/a&gt; turned October into the most productive month of the last year in regards to &lt;a href=&quot;https://docToolchain.github.io/docToolchain&quot;&gt;docToolchain&lt;/a&gt;:&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/hacktober_results2018.png&quot; style=&quot;max-width:100%;&quot; /&gt;
&lt;/div&gt;
&lt;p&gt;Not only did we reach my goal of 10 pull requests for &lt;a href=&quot;https://docToolchain.github.io/docToolchain&quot;&gt;docToolchain&lt;/a&gt;, Hacktoberfest also added new features and new contributors to &lt;a href=&quot;https://docToolchain.github.io/docToolchain&quot;&gt;docToolchain&lt;/a&gt;!!&lt;/p&gt;
&lt;p&gt;Regarding my personal experience with this years hacktoberfest, it was quite more intense than last years.&lt;br /&gt;
I already participated in last years hacktoberfest and so this time, I didn&apos;t expect to learn much from it.&lt;br /&gt;
That was wrong.&lt;/p&gt;
&lt;p&gt;I started out to create 5 PRs, and ended with 26 and with a better understanding of git.&lt;/p&gt;
&lt;p&gt;&amp;quot;What was so different to last year?&amp;quot; you may ask...&lt;/p&gt;
&lt;p&gt;Well, I noticed that I&apos;ve got several benefits from Hacktoberfest.&lt;br /&gt;
A PR shouldn&apos;t be a big thing - you do it several times a week, don&apos;t you?&lt;br /&gt;
No - at least I don&apos;t do it. For most projects I work on, I directly commit on branches and merge them.&lt;br /&gt;
I only seldom do PRs, and if I do them, they are trivial.&lt;/p&gt;
&lt;p&gt;I did a quick survey on twitter and it turns out that quite a lot of devs in my filter bubble also don&apos;t do PRs:&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;de&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;on your main project, how do you contribute code?&lt;/p&gt;&amp;mdash; Ralf D. Müller™ (@RalfDMueller) &lt;a href=&quot;https://twitter.com/RalfDMueller/status/1056233723753099264?ref_src=twsrc%5Etfw&quot;&gt;27. Oktober 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;p&gt;Also, it is not the same if you do just one PR or a bunch of PRs to the same repository where you have to re-sync your fork, do feature branches and rebases.&lt;/p&gt;
&lt;p&gt;Moreover, what you do often turns into a habit...&lt;/p&gt;
&lt;p&gt;In addition, contributing to open source is different than closed or inner source.&lt;br /&gt;
One big difference is remote work. Yes. An aspect I wasn&apos;t aware of.&lt;br /&gt;
With open source, you don&apos;t sit together in one room and invite the team to a meeting to discuss a change.&lt;br /&gt;
Instead &lt;strong&gt;you study the code and architecture of a system&lt;/strong&gt; and then eventually open an issue followed by a PR.&lt;br /&gt;
This is all across time zones and countries.&lt;br /&gt;
And when your PR gets accepted, it feels very productive.&lt;/p&gt;
&lt;p&gt;The part with &amp;quot;you study the code and architecture of a system&amp;quot; is quite important to me.&lt;br /&gt;
For most Github repositories, this is the harder part because the available documentation often only tells you how to use the system represented by the code but not how the code works under the hood.&lt;/p&gt;
&lt;p&gt;It showed me how important the various kinds of documentation are and that we should start to not only link to the source of the documentation (&amp;quot;improve this doc&amp;quot;) but also to the source code of the feature described in the documentation.&lt;br /&gt;
I think this would enable more people to contribute.&lt;/p&gt;
&lt;h3&gt;What are your thoughts on the barriers to contribute?&lt;/h3&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;PS: As promised, I donated 5€ for each PR to the &lt;a href=&quot;https://movember.com/&quot;&gt;Movember foundation&lt;/a&gt; and I doubled the amount to round it up to 100€.&lt;/p&gt;
&lt;h3&gt;Thanx for supporting docToolchain and the Movember foundation with your PRs!&lt;/h3&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;https://movember.com/&quot;&gt;&lt;img style=&quot;max-width:30%;&quot; src=&quot;https://cdn.movember.com/uploads/images/2018/Campaign/Movember%20Foundation_Iconic%20Mo_Black.jpg&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;

	  </description>
    </item>
    
    <item>
      <title>HttpBuilder-NG</title>
      <link>https://fiveandahalfstars.ninja/blog/2018/2018-08-10-httpbuilder-ng-redirect.html</link>
      <pubDate>Fri, 10 Aug 2018 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2018/2018-08-10-httpbuilder-ng-redirect.html</guid>
      <description>
      &lt;p&gt;When you write integration tests for your web application, you certainly need an http client.&lt;br /&gt;
But there are many on the market - too many and all with different approaches.&lt;/p&gt;
&lt;p&gt;I recently learned to love &lt;a href=&quot;https://http-builder-ng.github.io/http-builder-ng/&quot;&gt;HttpBuilder-NG&lt;/a&gt;.&lt;br /&gt;
I already was used to the old HttpBuilder which was often used with groovy, so I was quite eager to give the next generation a try.&lt;/p&gt;
&lt;p&gt;The approach it implements is totally different to what I was used to.&lt;br /&gt;
I just wanted to get a result back and then crawl over the given structure to find the properties I need. But HttpBuilder-NG comes with its own DSL which is very felxible but also has a learning curve.&lt;/p&gt;
&lt;p&gt;To make things easier for me, I came up with a generic template for my test approaches:&lt;/p&gt;
&lt;p&gt;{% highlight groovy %}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Grab(&apos;io.github.http-builder-ng:http-builder-ng-core:1.0.3&apos;)

import static groovyx.net.http.HttpBuilder.configure

def (statusCode, headers, body)

(statusCode, headers, body) = configure {
    request.uri = &amp;quot;http://example.com&amp;quot;
    request.headers = headers
}.get(List) { 
    response.success { FromServer resp, Object body -&amp;gt; 
        [
            resp.statusCode,
            resp.headers,
            body.toString()
        ]
    }
}   
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;{% endhighlight %}&lt;/p&gt;
&lt;p&gt;Wrapped in a function, this lets you execute various get requests with a given &lt;code&gt;uri&lt;/code&gt; and a set of &lt;code&gt;headers&lt;/code&gt;and will retrieve the http &lt;code&gt;statusCode&lt;/code&gt;, response &lt;code&gt;headers&lt;/code&gt; and the &lt;code&gt;body&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This template is a good starting point for further kind of requests and refinements where you, for instance, do not need all headers but only the location-header of redirects.&lt;/p&gt;
&lt;p&gt;As I already mentioned, there are many http clients available. And that is another strenght of HttpBuilder-NG: it is &amp;quot;just&amp;quot; a builder with the most common http clients under the hood.&lt;/p&gt;
&lt;p&gt;When you change the dependency from&lt;/p&gt;
&lt;p&gt;{% highlight groovy %}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Grab(&apos;io.github.http-builder-ng:http-builder-ng-okhttp:1.0.3&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;{% endhighlight %}&lt;/p&gt;
&lt;p&gt;to&lt;/p&gt;
&lt;p&gt;{% highlight groovy %}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Grab(&apos;io.github.http-builder-ng:http-builder-ng-core:1.0.3&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;{% endhighlight %}&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;{% highlight groovy %}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Grab(&apos;io.github.http-builder-ng:http-builder-ng-apache:1.0.3&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;{% endhighlight %}&lt;/p&gt;
&lt;p&gt;you switch the underlying http client from &lt;a href=&quot;http://square.github.io/okhttp/&quot;&gt;OkHttp&lt;/a&gt; to the java core implementation or &lt;a href=&quot;http://hc.apache.org/httpcomponents-client-ga/&quot;&gt;Apache HttpComponents&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another solution I would like to share is how to disable the client following redirects.&lt;br /&gt;
It seems that many people have the problem that they want to modify how the http client behaves in terms of redirects.&lt;br /&gt;
When it comes to testing, I always want to follow the redirects manually.&lt;br /&gt;
Bit all clients did it automatically.&lt;/p&gt;
&lt;p&gt;I googled a lot and was already at a point where I said &amp;quot;I will use the first http client where I manage to disable to follow redirects&amp;quot;.&lt;br /&gt;
Many hints you find on the web are for older versions or simply seem not to work.&lt;/p&gt;
&lt;p&gt;The code which finally worked for me is the following:&lt;/p&gt;
&lt;p&gt;{% highlight groovy %}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...

(statusCode, headers, body) = configure {
    request.uri = &amp;quot;http://example.com&amp;quot;
    request.headers = headers
    client.clientCustomizer { builder -&amp;gt;
        builder.followRedirects = false
        builder.followSslRedirects = false
    }
}.get(List) {

... 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;{% endhighlight %}&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Let's start to _model_ our software architecture!</title>
      <link>https://fiveandahalfstars.ninja/blog/2018/2018-02-05-architecture-model.html</link>
      <pubDate>Mon, 5 Feb 2018 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2018/2018-02-05-architecture-model.html</guid>
      <description>
      &lt;p&gt;As architect, you are often reminded that you should model your architecture and not just draw diagrams. But have you ever seen a real architecture model?&lt;/p&gt;
&lt;p&gt;I&apos;ve only seen some aspects modeled, not the whole architecture. I use Sparx Enterprise Architect now for aprox. 15 years, but still don&apos;t know how to use it the right way and really model my architecture.&lt;/p&gt;
&lt;h2&gt;why model and not just draw?&lt;/h2&gt;
&lt;p&gt;But let&apos;s first start with the basic question why we should model and not just draw. The results often look the same. And what do I mean by &amp;quot;model&amp;quot;?&lt;/p&gt;
&lt;p&gt;I remember a good example which I have read in a book, but I can&apos;t remember which one.&lt;br /&gt;
(if you know where I have stolen it, please contact me :-)&lt;/p&gt;
&lt;p&gt;Imagine, you have a sports car.&lt;/p&gt;
&lt;p&gt;Now imagine you have a small replica of this sports car. This is your model.&lt;/p&gt;
&lt;p&gt;It might not be like the real thing, but certain aspects are accurate. In this example, often the look is accurate but the engine won&apos;t work.&lt;/p&gt;
&lt;p&gt;That reminds me of the quote &amp;quot;All models are wrong, but some are useful&amp;quot; by George Box. So wether your model is an exact replica which you put on the shelve in your living room or it is a toy car with which your kids play - these models are useful and make sense for a certain use case, but an engineer might complain that it is wrong in terms of the engine details.&lt;/p&gt;
&lt;p&gt;Now imagine you have a detailed replica and you take some photos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;One of the outside view and one of the view from the driver&apos;s seat. These might be great picture if you want to sell your car.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;One of the motor and one of the bottom of the car. These might be great pictures for a mechanic.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These pictures are the views onto your model.&lt;/p&gt;
&lt;p&gt;You also could have drawn those views, but as you can see, it makes more sense to first create the model and then the views.&lt;/p&gt;
&lt;p&gt;It is the same with software architecture. Think about it!&lt;/p&gt;
&lt;p&gt;PS: in this example, it would have been even easier to take the pictures from the original sports car. But that does only work if your already have the finished product... &lt;a href=&quot;https://structurizr.com/&quot;&gt;https://structurizr.com/&lt;/a&gt; by Simon Brown takes this approach.&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Diagramme, aber richtig…</title>
      <link>https://fiveandahalfstars.ninja/blog/2018/2018-01-28-HHGDC5.html</link>
      <pubDate>Sun, 28 Jan 2018 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2018/2018-01-28-HHGDC5.html</guid>
      <description>
      &lt;p&gt;&lt;img src=&quot;https://jaxenter.de/wp-content/uploads/2017/10/HHGDC.png&quot; style=&quot;float: right; max-width:100%;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Architekturdokumentation besteht hauptsächlich aus Fließtext, Tabellen und Diagrammen. Fließtext und Tabellen sollten nach der letzten Folge kein Problem mehr sein. Jetzt zeigen wir Ihnen mehrere Optionen, Diagramme in Ihre Dokumentation zu integrieren: Einerseits den einfachen Weg des Referenzierens (mit einigen möglichen Optionen) und alternativ Diagrams-as-Code, was gut zu Titel und Inhalt dieser Kolumne passt. So viel sei allerdings schon verraten: Leider eignet sich der letztgenannte (PlantUML-basierte) Ansatz nur für ganz wenige Arten von Diagrammen. Aber eins nach dem anderen – fangen wir mit den einfachen Dingen an.&lt;/p&gt;
&lt;p&gt;weiterlesen auf &lt;a href=&quot;https://jaxenter.de/hitchhikers-guide-docs-code-diagramme-66357&quot;&gt;jaxenter.de&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Den mittlerweile sechsten Teil der Kolumne finden Sie in der &lt;a href=&quot;https://jaxenter.de/magazine/java-magazin/&quot;&gt;aktuellen Ausgabe 03.2018 des JavaMagazins&lt;/a&gt;&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>AsciiDoc-Features für Pragmatisches</title>
      <link>https://fiveandahalfstars.ninja/blog/2018/2018-01-21-HHGDC4.html</link>
      <pubDate>Sun, 21 Jan 2018 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2018/2018-01-21-HHGDC4.html</guid>
      <description>
      &lt;p&gt;&lt;img src=&quot;https://jaxenter.de/wp-content/uploads/2017/10/HHGDC.png&quot; style=&quot;float: right; max-width:100%;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In den letzten Ausgaben haben wir gezeigt, wie Sie AsciiDoc-Dokumente modular aufbauen und in verschiedene Zielformate wie PDF, DOCX oder Confluence konvertieren können. Diesmal gehen wir auf ein paar der Features von AsciiDoc ein, die unserer Meinung nach bei Architekturdokumentation nützlich sein können.&lt;/p&gt;
&lt;p&gt;weiterlesen auf &lt;a href=&quot;https://jaxenter.de/asciidoc-features-66027&quot;&gt;jaxenter.de&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Den mittlerweile fünften Teil der Kolumne finden Sie in der &lt;a href=&quot;https://jaxenter.de/magazine/java-magazin/&quot;&gt;aktuellen Ausgabe 02.2018 des JavaMagazins&lt;/a&gt;&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Open Source is GREAT!</title>
      <link>https://fiveandahalfstars.ninja/blog/2018/2018-01-14-open-source-is-great.html</link>
      <pubDate>Sun, 14 Jan 2018 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2018/2018-01-14-open-source-is-great.html</guid>
      <description>
      &lt;p&gt;Some thing you just have to experience yourself before you realize it.&lt;br /&gt;
One of those things is the power of open source.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/binary_earth_presenter_media.png&quot; style=&quot;max-width:100%;&quot; /&gt;
&lt;/div&gt;
&lt;p&gt;I am just now sitting over a new project where I need some documentation.&lt;br /&gt;
So I just installed the current version of &amp;quot;my own&amp;quot; open source project &lt;a href=&quot;https://github.com/docToolchain/docToolchain&quot;&gt;docToolchain&lt;/a&gt;&lt;br /&gt;
and had to realize that I first had to study the manual on how to install the current version.&lt;/p&gt;
&lt;p&gt;The project evolved without me and now has the option to be installed as a tool which is invoked through the &lt;code&gt;doctoolchain&lt;/code&gt; command instead of beeing a geeky gradle script.&lt;/p&gt;
&lt;p&gt;This aspect of Open Source Software is underestimated by many companies who fear that if they open source software, they lose the value of their software to the community.&lt;br /&gt;
But for certain types of software, the opposite is the case.&lt;br /&gt;
The software is enriched by the community and you get back a value which can be much higher than the original value you had in your software.&lt;/p&gt;
&lt;p&gt;The basis for this effect is a great community.&lt;/p&gt;
&lt;p&gt;So, again - thanx to all of you who support docToolchain and other open source projects!&lt;br /&gt;
The world relies on open source and hence relies on you!&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>looking back at a great 2017</title>
      <link>https://fiveandahalfstars.ninja/blog/2018/2018-01-07-eoy-2017.html</link>
      <pubDate>Sun, 7 Jan 2018 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2018/2018-01-07-eoy-2017.html</guid>
      <description>
      &lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/2017.png&quot; style=&quot;max-width:100%;&quot; /&gt;
&lt;/div&gt;
&lt;p&gt;The year is already seven days old, but it is still time to take a quick look back.&lt;/p&gt;
&lt;p&gt;2017 was a great year for me regarding my community activity and the progress of my open source project &lt;a href=&quot;https://github.com/docToolchain/docToolchain&quot;&gt;docToolchain&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This year, I had several chances to talk about Spock &amp;amp; Geb (thanx to &lt;a href=&quot;https://twitter.com/DevOpsWuerzburg&quot;&gt;DevOpsWuerzburg&lt;/a&gt; for inviting me and &lt;a href=&quot;https://twitter.com/tokraft&quot;&gt;Tobias Kraft&lt;/a&gt; for giving me the chance to be his co-speaker) and Docs-as-Code plus &lt;a href=&quot;https://github.com/docToolchain/docToolchain&quot;&gt;docToolchain&lt;/a&gt; (thanx to &lt;a href=&quot;https://twitter.com/jaxcon&quot;&gt;JAX&lt;/a&gt;, the &lt;a href=&quot;https://twitter.com/SoftwArchSummit&quot;&gt;Software Architecture Summit&lt;/a&gt; and the &lt;a href=&quot;https://twitter.com/JUG_DA&quot;&gt;JUG Darmstadt&lt;/a&gt; for inviting me and to &lt;a href=&quot;https://twitter.com/sippsack&quot;&gt;Falk Sippach&lt;/a&gt; for combining our talks!). The slides are all available on &lt;a href=&quot;https://speakerdeck.com/rdmueller&quot;&gt;speakerdeck&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A special thank you goes out to &lt;a href=&quot;https://twitter.com/gernotstarke&quot;&gt;Gernot Starke&lt;/a&gt; who helped me to prepare the JAX-Talk and Architecture Summit-Workshop and let me be his co-speaker! Together we also wrote the &lt;a href=&quot;https://jaxenter.de/tag/hhgdc&quot;&gt;Hitchhiker’s Guide to Docs as Code&lt;/a&gt; as series of articles for the german &lt;a href=&quot;https://entwickler.de/java-magazin&quot;&gt;Java Magazin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These where all great experience and I hope I can build on these this year. I already have a slot for a talk about docs-as-code at the &lt;a href=&quot;https://entwicklertag.de/frankfurt/2018/docs-code-arc42-asciidoc-gradle-co-im-einsatz&quot;&gt;Entwicklertag Frankfurt&lt;/a&gt; and I hope more chances will come up.&lt;/p&gt;
&lt;p&gt;The best about all these events where the talks with you - the audience - afterwards and the feedback I could collect. Documentation as a topic seems to be more interesting than I thought and people see that the docs-as-code aproach makes sense.&lt;/p&gt;
&lt;p&gt;This is also reflected by the momentum the &lt;a href=&quot;https://github.com/docToolchain/docToolchain&quot;&gt;docToolchain&lt;/a&gt; project gained this year. It now has a &lt;a href=&quot;https://doctoolchain.github.io/docToolchain/&quot;&gt;full blown manual&lt;/a&gt; and more than eight &lt;a href=&quot;https://doctoolchain.github.io/docToolchain/#_acknowledgements_and_contributors&quot;&gt;contributors&lt;/a&gt; who contributed 2017 more features than I did. So it is now a project which is owned by the community - that&apos;s a great feeling! Thanx to all of you!&lt;/p&gt;
&lt;p&gt;Through the community contributed features, &lt;a href=&quot;https://github.com/docToolchain/docToolchain&quot;&gt;docToolchain&lt;/a&gt; gained the ability to export Excel, PPT and Visio. There will soon be a point where I  have to split the architecture diagram into several ones:&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/docToolchainOverview.png&quot; style=&quot;max-width:100%;&quot; /&gt;
&lt;/div&gt;
&lt;p&gt;Speaking of this diagram - docToolchain even managed to be referenced in the newest edition of &lt;a href=&quot;https://twitter.com/gernotstarke&quot;&gt;Gernot Starkes&lt;/a&gt; book &amp;quot;&lt;a href=&quot;https://www.amazon.de/Effektive-Softwarearchitekturen-Ein-praktischer-Leitfaden/dp/3446452079/ref=dp_ob_title_bk&quot;&gt;Effektive Softwarearchitekturen&lt;/a&gt;&amp;quot;!&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;a href=&quot;https://www.amazon.de/Effektive-Softwarearchitekturen-Ein-praktischer-Leitfaden/dp/3446452079/ref=as_li_ss_il?ie=UTF8&amp;linkCode=li2&amp;tag=bit0c-21&amp;linkId=3c87d6a247929a581d8af9376723825b&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;//ws-eu.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;ASIN=3446452079&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=DE&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=bit0c-21&quot; &gt;&lt;/a&gt;&lt;img src=&quot;https://ir-de.amazon-adsystem.com/e/ir?t=bit0c-21&amp;l=li2&amp;o=3&amp;a=3446452079&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;
&lt;/div&gt;
&lt;p&gt;I nearly forgot to mention that docToolchain was also mentioned by &lt;a href=&quot;https://twitter.com/simonbrown&quot;&gt;Simon Brown&lt;/a&gt; in one tweet together with &lt;a href=&quot;https://twitter.com/Grady_Booch&quot;&gt;Grady Booch&lt;/a&gt; - isn&apos;t that cool?&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;de&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;I did a short interview at &lt;a href=&quot;https://twitter.com/VoxxedAthens?ref_src=twsrc%5Etfw&quot;&gt;@VoxxedAthens&lt;/a&gt; with &lt;a href=&quot;https://twitter.com/katharineCodes?ref_src=twsrc%5Etfw&quot;&gt;@katharineCodes&lt;/a&gt; recently -&amp;gt; &lt;a href=&quot;https://t.co/l0mWJ2ioy0&quot;&gt;https://t.co/l0mWJ2ioy0&lt;/a&gt; … hat tips to &lt;a href=&quot;https://twitter.com/Grady_Booch?ref_src=twsrc%5Etfw&quot;&gt;@Grady_Booch&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://twitter.com/docToolchain?ref_src=twsrc%5Etfw&quot;&gt;@docToolchain&lt;/a&gt;&lt;/p&gt;&amp;mdash; Simon Brown (@simonbrown) &lt;a href=&quot;https://twitter.com/simonbrown/status/880812832010448896?ref_src=twsrc%5Etfw&quot;&gt;30. Juni 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;(btw: I love the C4 approach invented by &lt;a href=&quot;https://twitter.com/simonbrown&quot;&gt;Simon Brown&lt;/a&gt; and his books on &lt;a href=&quot;https://softwarearchitecturefordevelopers.com/&quot;&gt;Software Architecture for Developers&lt;/a&gt;)&lt;br /&gt;
I am also very happy that the year gave me lots of chances to meet many of those great people from my twitter time line and talk over a pizza or a beer with them. I learned a lot from all of you!&lt;/p&gt;
&lt;p&gt;We are dwarfs standing on the shoulders of giants - in this sense, I would also like to thanx the &lt;a href=&quot;https://twitter.com/asciidoctor&quot;&gt;Asciidoctor&lt;/a&gt;, the &lt;a href=&quot;https://twitter.com/ApacheGroovy&quot;&gt;Apache Groovy&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/gradle&quot;&gt;Gradle&lt;/a&gt; project teams who all created the wonderful basis for docToolchain.&lt;/p&gt;
&lt;p&gt;Hope to see you all again in 2018!&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Dokumentationen als Code</title>
      <link>https://fiveandahalfstars.ninja/blog/2017/2017-12-29-HHGDC3.html</link>
      <pubDate>Fri, 29 Dec 2017 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2017/2017-12-29-HHGDC3.html</guid>
      <description>
      &lt;p&gt;&lt;img src=&quot;https://jaxenter.de/wp-content/uploads/2017/10/HHGDC.png&quot; style=&quot;float: right; max-width:100%;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In der letzten Folge dieser Kolumne haben wir gezeigt, wie Sie Ihre AsciiDoc-Dokumente modular aufbauen können.&lt;br /&gt;
In der dritten Folge der Kolumne erklären wir am Beispiel der Formate PDF, DOCX, Confluence und EPUB, wie sich verschiedene Ausgabeformate aus Ihrem AsciiDoc-Input erzeugen lassen.&lt;/p&gt;
&lt;p&gt;weiterlesen auf &lt;a href=&quot;https://jaxenter.de/docs-as-code-65644&quot;&gt;jaxenter.de&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Den mittlerweile fünften Teil der Kolumne finden Sie in der &lt;a href=&quot;https://jaxenter.de/magazine/java-magazin/&quot;&gt;aktuellen Ausgabe 02.2018 des JavaMagazins&lt;/a&gt;&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Modulare Dokumentationen</title>
      <link>https://fiveandahalfstars.ninja/blog/2017/2017-11-08-HHGDC2.html</link>
      <pubDate>Wed, 8 Nov 2017 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2017/2017-11-08-HHGDC2.html</guid>
      <description>
      &lt;p&gt;&lt;img src=&quot;https://jaxenter.de/wp-content/uploads/2017/10/HHGDC.png&quot; style=&quot;float: right; max-width:100%;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In der letzten Ausgabe haben wir gezeigt, wie Sie mithilfe von AsciiDoc schnell zu ordentlich gestalteten Dokumenten kommen können.&lt;br /&gt;
In der zweiten Folge unserer Kolumne möchten wir Ihnen Strukturierung und Modularisierung von Dokumentation vorstellen, einerseits zur Erleichterung von Teamarbeit, andererseits zur Verwendung einzelner Dokuteile für verschiedene Zielgruppen.&lt;/p&gt;
&lt;p&gt;weiterlesen auf &lt;a href=&quot;https://jaxenter.de/documentation-modularisierung-63743&quot;&gt;jaxenter.de&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Den dritten Teil der Kolumne finden sie in der &lt;a href=&quot;https://jaxenter.de/magazine/java-magazin/&quot;&gt;aktuellen Ausgabe 12.2017 des JavaMagazins&lt;/a&gt;&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Neue Kolumne</title>
      <link>https://fiveandahalfstars.ninja/blog/2017/2017-10-18-HHGDC1.html</link>
      <pubDate>Wed, 18 Oct 2017 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2017/2017-10-18-HHGDC1.html</guid>
      <description>
      &lt;p&gt;&lt;img src=&quot;https://jaxenter.de/wp-content/uploads/2017/10/HHGDC.png&quot; style=&quot;float: right; max-width:100%;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Dokumentation gehört zu den großen Übeln der Softwarezunft.&lt;br /&gt;
Denn Software zu dokumentieren ist oft mühselig, zeitraubend und schlicht und ergreifend langweilig.&lt;br /&gt;
Dass dem nicht so seien muss, zeigen die beiden Autoren Gernot Starke und Ralf D. Müller in ihrer neuen Kolumne.&lt;br /&gt;
Ihr Ansatz ist die Dokumentation wie Code zu behandeln: Docs as Code.&lt;/p&gt;
&lt;p&gt;weiterlesen auf &lt;a href=&quot;https://jaxenter.de/docs-as-code-asciidoctor-62432&quot;&gt;jaxenter.de&lt;/a&gt;&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>plantUML with Asciidoctor-pdf</title>
      <link>https://fiveandahalfstars.ninja/blog/2017/2017-05-01-plantUML-and-pdf.html</link>
      <pubDate>Mon, 1 May 2017 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2017/2017-05-01-plantUML-and-pdf.html</guid>
      <description>
      &lt;p&gt;The last few days I had to learn the hard way that plantUML (as part of asciidoctor-diagram) is not a frient of asciidoctor-pdf.&lt;/p&gt;
&lt;p&gt;I always thought that having plantUML for HTML rendering up and running with asciidoctor also means that the PDF backend would be running fine.&lt;/p&gt;
&lt;p&gt;Unfortunately, asciidoctor-pdf is looking in the &lt;code&gt;source&lt;/code&gt;-folder for the generated plantUML images and can&apos;t find them there.&lt;/p&gt;
&lt;p&gt;I didn&apos;t quite get the whole picture - which module is picking up the images from where or generates them in which folder, but I got the impression that the problem is quite complex.&lt;br /&gt;
Dan Allen pointed me to some comments which &lt;a href=&quot;https://github.com/asciidoctor/asciidoctor-gradle-examples/issues/15#issuecomment-298003598&quot;&gt;describe solutions&lt;/a&gt; (the Asciidoctor community is really great), but while I was trying to find a solution which fits my case, I got the feeling that I will get standard images &lt;em&gt;or&lt;/em&gt; plantUML up and running, but not &lt;em&gt;both&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;ve now got a solution which I think is quite ok:&lt;/p&gt;
&lt;p&gt;First, I splitted the generation of HTML and PDF into two seperate tasks:&lt;/p&gt;
&lt;p&gt;{% highlight gradle %}&lt;br /&gt;
tasks.withType(AsciidoctorTask) { docTask -&amp;gt;&lt;br /&gt;
outputDir = file(targetDir)&lt;br /&gt;
sourceDir = file(srcDir)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &apos;pdf-stylesdir&apos;: &apos;pdfTheme&apos;,
        &apos;pdf-style&apos;: &apos;custom&apos;,
        &apos;source-highlighter&apos;: &apos;coderay&apos;,
        &apos;imagesdir&apos;: &apos;images&apos;,
        &apos;toc&apos;: &apos;left&apos;,
        &apos;icons&apos;: &apos;font&apos;,
        &apos;javaVersion&apos;         : &amp;quot;$javaVersion&amp;quot;,
        &apos;currentDate&apos;         : &amp;quot;$currentDate&amp;quot;,
        &apos;allow-uri-read&apos;      : true
// ...

// configure source and output files and folders
sourceDir = file(&apos;src/docs&apos;)
sources {
    include &apos;arc42-venom.adoc&apos;
    include &apos;index-orga.adoc&apos;
}
outputDir = file(&apos;build/docs&apos;)
// good to see what the build is doing...
logDocuments = true

requires = [&apos;asciidoctor-diagram&apos;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;task generateHTML (&lt;br /&gt;
type: AsciidoctorTask,&lt;br /&gt;
description: &apos;use html5 as asciidoc backend&apos;) {&lt;br /&gt;
attributes &lt;br /&gt;
&apos;plantUMLDir&apos;         : &apos;&apos;&lt;br /&gt;
backends = [&apos;html5&apos;]&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;task generatePDF (&lt;br /&gt;
type: AsciidoctorTask,&lt;br /&gt;
description: &apos;use html5 as asciidoc backend&apos;) {&lt;br /&gt;
attributes &lt;br /&gt;
&apos;plantUMLDir&apos;         : file(&apos;build/docs/images/plantUML/&apos;).path&lt;br /&gt;
backends = [&apos;pdf&apos;]&lt;br /&gt;
}&lt;br /&gt;
{% endhighlight %}&lt;/p&gt;
&lt;p&gt;Second (already included in the source above), I added an attribute &lt;code&gt;plantUMLDir&lt;/code&gt; which specifies the &lt;em&gt;absolute&lt;/em&gt; path to a folder where I want to have my plantUML images generated to.&lt;/p&gt;
&lt;p&gt;So, my trick now is to use this &lt;em&gt;absolute&lt;/em&gt; path in my plantUML diagram definitions&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[plantuml,&amp;quot;{plantUMLDir}image_name&amp;quot;,png]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and this seems to work :-)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;for HTML, plantUML images are referenced relative to the document&lt;/li&gt;
&lt;li&gt;for PDF, plantUML images are are referenced absolute, but since they are stored within the pdf, this does not matter&lt;/li&gt;
&lt;li&gt;images are rendered ok in HTML and PDF&lt;/li&gt;
&lt;li&gt;plantUML is rendered ok in HTML and PDF&lt;/li&gt;
&lt;li&gt;plantUML files are created in &lt;code&gt;build&lt;/code&gt;-folder&lt;/li&gt;
&lt;/ul&gt;

	  </description>
    </item>
    
    <item>
      <title>systematically improve code and structures</title>
      <link>https://fiveandahalfstars.ninja/blog/2016/2016-10-10-improve.html</link>
      <pubDate>Mon, 10 Oct 2016 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2016/2016-10-10-improve.html</guid>
      <description>
      &lt;p&gt;Last week, I had the chance to attend a three day training on how to systematically improve software systems. It is called &amp;quot;IMPROVE&amp;quot;  and is given by &lt;a href=&quot;http://www.b-agile.de/&quot;&gt;Dr. Peter Hruschka&lt;/a&gt; and &lt;a href=&quot;http://gernotstarke.de/&quot;&gt;Dr. Gernot Starke&lt;/a&gt;. The german description can be found here: &lt;a href=&quot;http://www.arc42.de/improve.html&quot;&gt;http://www.arc42.de/improve.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The training is based on the &lt;a href=&quot;http://aim42.org&quot;&gt;aim42&lt;/a&gt; initiative and enriched by the broad knowledge and experience of the two speakers. What I liked most where the two parts on how to do estimates the right way and how to convince the management to let you work on technical debt.&lt;/p&gt;
&lt;p&gt;Today I already started to implement what I learned and created a technical debt list for &lt;a href=&quot;github.com/rdmueller/docToolchain&quot;&gt;docToolchain&lt;/a&gt; and tomorrow I will start to put estimates on each issue...&lt;/p&gt;
&lt;p&gt;More can be found on the english website of &lt;a href=&quot;http://aim42.org&quot;&gt;aim42&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;de&quot;&gt;&lt;p lang=&quot;de&quot; dir=&quot;ltr&quot;&gt;Reduzierte Wartungskosten durch evolutionäre Verbesserung: &lt;a href=&quot;https://t.co/soZUqvXXPx&quot;&gt;https://t.co/soZUqvXXPx&lt;/a&gt; Trainingsimpressionen mit Peter Hruschka &amp;amp; &lt;a href=&quot;https://twitter.com/gernotstarke&quot;&gt;@gernotstarke&lt;/a&gt; &lt;a href=&quot;https://t.co/6066CrxLIY&quot;&gt;pic.twitter.com/6066CrxLIY&lt;/a&gt;&lt;/p&gt;&amp;mdash; arc42 (@arc42Tipps) &lt;a href=&quot;https://twitter.com/arc42Tipps/status/784379614676344832&quot;&gt;7. Oktober 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;de&quot;&gt;&lt;p lang=&quot;de&quot; dir=&quot;ltr&quot;&gt;Bauen versus Basteln - &lt;a href=&quot;https://twitter.com/gernotstarke&quot;&gt;@gernotstarke&lt;/a&gt; über die teilweise grotesken Zustände der SW-Entwicklung &lt;a href=&quot;https://t.co/FAVymyzcc6&quot;&gt;https://t.co/FAVymyzcc6&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/aim42?src=hash&quot;&gt;#aim42&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/architecture?src=hash&quot;&gt;#architecture&lt;/a&gt;&lt;/p&gt;&amp;mdash; arc42 (@arc42Tipps) &lt;a href=&quot;https://twitter.com/arc42Tipps/status/784373145394380800&quot;&gt;7. Oktober 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

	  </description>
    </item>
    
    <item>
      <title>Groovy is Java is Groovy...</title>
      <link>https://fiveandahalfstars.ninja/blog/2016/2016-5-9-Groovy-is-Java.html</link>
      <pubDate>Mon, 9 May 2016 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2016/2016-5-9-Groovy-is-Java.html</guid>
      <description>
      &lt;p&gt;There still seem to be some Java-Developers who are afraid of&lt;br /&gt;
mixing their Java codebase with the power of Groovy.&lt;/p&gt;
&lt;p&gt;Some time ago, it was a valid argument that the dependency&lt;br /&gt;
to the groovy-all.jar would blow up the generated application,&lt;br /&gt;
but today many frameworks like Jasper-Reports, Apache-Camel and others might already add the&lt;br /&gt;
groovy-all.jar to the class path of your application. So there is no reason anymore&lt;br /&gt;
not to use Groovy in your project.&lt;/p&gt;
&lt;p&gt;The following snippets will show you how easy it is to combine Java und Groovy, because Groovy is Java and Java is Groovy...&lt;/p&gt;
&lt;p&gt;This example assumes that you have Groovy and Java installed and &lt;code&gt;groovy-all-2.4.6.jar&lt;/code&gt; is available in your work directory.&lt;/p&gt;
&lt;p&gt;Create a simple Java class which just greets Groovy:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HelloGroovy.java&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class HelloGroovy {
	public static void main(String[] args) {
		System.out.println(&amp;quot;Hello Groovy. This is java!&amp;quot;);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...and compile it...&lt;/p&gt;
&lt;p&gt;&lt;code&gt;javac -cp . HelloGroovy.java&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now create a Groovy-Script which greets Java and calls the Java class from above&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HelloJava.groovy&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;println &amp;quot;Hello Java, this is Groovy!&amp;quot;
HelloGroovy.main(); //call the first java-snippet
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...and compile it...&lt;/p&gt;
&lt;p&gt;&lt;code&gt;groovyc -cp . HelloJava.groovy&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now create a third file which contains a Java class which calls the class created by the Groovy-Script&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Test.java&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;class Test {
	public static void main(String[] args) {
		System.out.println(&amp;quot;Java &amp;amp; Groovy = Dream-Team!&amp;quot;);
		HelloJava.main();
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...and compile it. This time, we need the &lt;code&gt;groovy-all.jar&lt;/code&gt; in the classpath:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;javac -cp &amp;quot;.;groovy-all-2.4.6.jar&amp;quot; Test.java&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That&apos;s it. Now let&apos;s execute the test class:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ java -cp &amp;quot;.;groovy-all-2.4.6.jar&amp;quot; Test
Java &amp;amp; Groovy = Dream-Team!
Hello Java, this is Groovy!
Hello Groovy. This is java!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wasn&apos;t that easy?&lt;/p&gt;
&lt;p&gt;PS: yes, this is very old knowledge, but sometimes the good things have to be repeated over and over again...&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>A Groovy Notebook</title>
      <link>https://fiveandahalfstars.ninja/blog/2016/2016-4-30-Groovy-Notebook.html</link>
      <pubDate>Sat, 30 Apr 2016 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2016/2016-4-30-Groovy-Notebook.html</guid>
      <description>
      &lt;p&gt;From time to time I stumble upon a web application which lets you write notebooks like the ones you know from Mathematica. They let you mix formatted text which explains your code with code snippets. The output of those snippets is displayed and the code builds up snippet by snippet.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/Jypiter.png&quot; style=&quot;width:100%;&quot; /&gt;
&lt;span style=&quot;font-size: smaller;&quot;&gt;Taken from the &lt;a href=&quot;http://blog.jupyter.org/2016/01/08/notebook-4-1-release/&quot;&gt;Jypter Blog&lt;/a&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;This time it was &lt;a href=&quot;http://jupyter.org/&quot;&gt;Jypiter&lt;/a&gt;, formerly known as &lt;a href=&quot;http://ipython.org/notebook.html&quot;&gt;IPython Notebook&lt;/a&gt;. It evolved from a notebook just for Python to a cool solution suitable for all kind of languages. Unfortunately, Groovy isn&apos;t yet in the list of supported languages.&lt;/p&gt;
&lt;p&gt;Since Python is not my mother tongue and I couldn&apos;t find good documentation on how to support an additional language, I thought about other ways to create a notebook for Groovy.&lt;/p&gt;
&lt;p&gt;Inspired by the talk &lt;a href=&quot;http://greachconf.com/speakers/stephan-classen-make-your-asciidoctor-groovy/&quot;&gt;&amp;quot;Make your Asciidoctor Groovy&amp;quot;&lt;/a&gt; by Stephan Classen (which I unfortunately haven&apos;t attended), I decided to create an asciidoctorj plugin in Groovy which lets you execute Groovy code inline.&lt;/p&gt;
&lt;p&gt;There are already great examples of plugins written in Groovy, so I had a good starting point:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stephan Classen: &lt;a href=&quot;https://github.com/asciidoctor/asciidoctorj-screenshot&quot;&gt;asciidoctorj-screenshot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;mrhaki: &lt;a href=&quot;http://mrhaki.blogspot.de/2014/08/awesome-asciidoc-write-extensions-using.html&quot;&gt;Awesome Asciidoctor: Write Extensions Using Groovy (or Java)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Andreas Almiray: &lt;a href=&quot;http://www.jroller.com/aalmiray/entry/gradle_glam_custom_asciidoctor_extensions&quot;&gt;Gradle Glam: custom asciidoctor extensions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I took one of them as starting point and came up with &lt;a href=&quot;https://github.com/rdmueller/asciidoctorj-groovy&quot;&gt;my own project&lt;/a&gt;. The core of the extension is shown here:&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/rdmueller/037182fb79193d98835db2507edf7759.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;It is activated whenever asciidoctor hits a &lt;code&gt;[groovy]&lt;/code&gt; block. It then takes the content of the block, executes it and renders the original script together with the output. Infortunately, I couldn&apos;t find a way to return two different blocks in my extension - one which renders the source with highlighting and one which renders the pre-formatted output - so I had to do an ugly workaround which directly renders HTML. Do the simplest think which works :-)&lt;/p&gt;
&lt;p&gt;Here is an example of the static rendered output: &lt;a href=&quot;https://rawgit.com/rdmueller/asciidoctorj-groovy/master/example.html&quot;&gt;example.html&lt;/a&gt; with the corrsponding &lt;a href=&quot;https://github.com/rdmueller/asciidoctorj-groovy/blob/master/src/asciidoc/index.adoc&quot;&gt;input&lt;/a&gt;.&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Wacom Bamboo Spark - could have been so much more...</title>
      <link>https://fiveandahalfstars.ninja/blog/2016/2016-4-28-bamboo-spark.html</link>
      <pubDate>Thu, 28 Apr 2016 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2016/2016-4-28-bamboo-spark.html</guid>
      <description>
      &lt;p&gt;Bad news first: I guess I do not belong to the target group of the &lt;a href=&quot;http://www.wacom.com/en-us/products/mobile-accessories/bamboo-spark&quot;&gt;Wacom Bamboo Spark&lt;/a&gt; :-)&lt;/p&gt;
&lt;p&gt;My week began with a Mail from Amazon telling me that there they have a special offer for one of my Wishlist items: the Bamboo Spark digital notepad. I couldn&apos;t resist and ordered it, but sone came doubts: do I have any use case for it?&lt;/p&gt;
&lt;p&gt;Yesterday the Spark arrived. As always with Wacom, the unboxing gives you the feeling that you&apos;ve made the right decision and have bought a well designed product. The setup is also a no brainer and you can start to write and sketch immediately. The pen feels like a normal pen and the paper - well it is just normal paper.&lt;/p&gt;
&lt;p&gt;The digitizer works very accurate. The simple status LED shows you if you are on a blank page (from the Spark&apos;s point of view) or if it already has some content. A press of the button advanced to the next blank page.&lt;/p&gt;
&lt;p&gt;The sync with the mobile device seems to be activated whenever you switch to a new blank page. There is no other control to start the sync. That&apos;s something I had to figure out, but it is ok. As soon as the pages are synced to the wacom cloud, you can convert them to plain text, PDF or image. The text recognition works quite well, even for mixed language content.&lt;/p&gt;
&lt;p&gt;So far so good. If you want to sync what you&apos;ve written and sketched, this product is perfect. But that seems to be all functionality you get with the bamboo spark app. Nothing more. So, I guess there are people who need exactly this functionality and for them, the bamboo spark is the perfect product.&lt;/p&gt;
&lt;h2&gt;But I hoped to get a bit more&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;compared to scanner apps like &lt;a href=&quot;http://whitelines.se/link/&quot;&gt;Whitelines Link&lt;/a&gt; it could be much more intelligent. Whitelines only captures the paper by camera, but it offers three checkboxes through which you can tell the app to directly store the captures image in evernote, dropbox or send it via mail. Such a functionality should be a quick win for wacom&lt;/li&gt;
&lt;li&gt;the spark uses &amp;quot;the soon-to-be industry standard WILL™ universal ink files&amp;quot;. But when you try to get more information about this format, you have to sign agreements in order to get the SDK. WILL seems to be a zip file with a binary data file as main content. It would have been nice if the file format would have been easier to use.&lt;/li&gt;
&lt;li&gt;but you can also export your written notes as plain text. And this seems to be the key to additional, self build functionality&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Ideas on how to hack the functionality&lt;/h2&gt;
&lt;h3&gt;Plain Text Processing&lt;/h3&gt;
&lt;p&gt;Since the first anoto smart pens like the &lt;a href=&quot;https://www.livescribe.com/&quot;&gt;livescribe smartpen&lt;/a&gt; hit the market, I dreamed of functionality where you use plain paper to create input for our personal digital assistant (PDA) as the devices where called back then. Today I would like to use the bamboo spark to interact with my smartphone. Here are basically three simple use cases&lt;/p&gt;
&lt;h4&gt;1. write a simple note and send it via mail&lt;/h4&gt;
&lt;p&gt;This could be as simple as writing a note like this on the spark:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mailto: someone@example.com
Please don&apos;t forget to send me that info...
Cheers,
Ralf
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;2. write a to-do which will added to your favorite to-do list&lt;/h4&gt;
&lt;p&gt;same pattern:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ToDo: buy some beer for the party next weekend&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;3. ... or add something to your calendar&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Date: 29.04. 19:00 Java User Group Meetup&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And yep, it basically works! You can scribble these notes on the spark, convert them to text and then send them - for instance as email - to a script which does a further processing. Not build in, but possible and easy to implement. But this is unfortunately not an automated step since there is no API for the wacom cloud (at least none I am aware of) and so you have to convert your notes manually to plain text and send them. Each page by its own :-(&lt;/p&gt;
&lt;h3&gt;Extract Graphical Data&lt;/h3&gt;
&lt;p&gt;Another Idea is to process the strokes for additional functionality. The system should be able to give you the timing of the strokes along with the strokes themselves. So in addition to the OCR, you could implement functionality like the whitelines checkboxes - the system should be able to recognize a checkmark in a certain position or a special symbol.&lt;/p&gt;
&lt;p&gt;The WILL format seems to be the right way, but since it is proprietary, I don&apos;t want to take this route. It would be different if it would be more open.&lt;/p&gt;
&lt;p&gt;So I checked the exported PDF - bingo. The PDF contains not the strokes but the drawing - e.g. for each line a polygon which describes the border of the stroke. And those polygons seem to be even in the order of drawing. In order to give it a try, I create a small javascript which visualizes the PDF drawing:&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;600&quot; src=&quot;//jsfiddle.net/RDMueller/wnraf3rp/3/embedded/result,js/&quot; allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;
&lt;!--script async src=&quot;https://jsfiddle.net/RDMueller/wnraf3rp/3/embed/result,js,html/&quot;&gt;&lt;/script--&gt;
&lt;h2&gt;tl;dr&lt;/h2&gt;
&lt;p&gt;The wacom bamboo spark is a great tool if you want to have digital copies of your handwritten sketches and notes. But unfortunately there is no extra functionality out of the box. Hacking is possible, wacom could make it easier.&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Serialize a Map as JSON or YAML</title>
      <link>https://fiveandahalfstars.ninja/blog/2016/2016-4-6-json.html</link>
      <pubDate>Wed, 6 Apr 2016 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2016/2016-4-6-json.html</guid>
      <description>
      &lt;p&gt;When working in a web environment, you often have to transfer arbitrary data like lists or maps as String of the network.&lt;/p&gt;
&lt;p&gt;The followin Gist shows how to solve this by serializing a list or map as JSON or YAML. In addition, it&lt;br /&gt;
shows how Groovy does it an a very elegant and clean way.&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/rdmueller/793d262862270eda8d3a0b5c2e9e46da.js&quot;&gt;&lt;/script&gt;

	  </description>
    </item>
    
    <item>
      <title>Jatumba!</title>
      <link>https://fiveandahalfstars.ninja/blog/2016/2016-3-10-javaland.html</link>
      <pubDate>Thu, 10 Mar 2016 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2016/2016-3-10-javaland.html</guid>
      <description>
      &lt;p&gt;Zwei Tage Javaland liegen gerade hinter mir. Zusammen mit &lt;a href=&quot;https://twitter.com/tokraft&quot;&gt;Tobias Kraft&lt;/a&gt; hatte ich die tolle Gelegenheit unseren Vortrag über Spock und Geb nochmal vor einem größeren Publikum vorzutragen.&lt;/p&gt;
&lt;p&gt;Die zwei Tage waren natürlich vollgepackt mit Vorträgen, gutem Essen und guter Laune. Im Netzt gibt es schon einige gute Zusammenfassungen der Tage z.B. bei &lt;a href=&quot;http://blog.exensio.de/2016/03/javaland-2016.html&quot;&gt;exensio&lt;/a&gt; und &lt;a href=&quot;https://develishdevelopment.wordpress.com/2016/03/09/javaland-2016-conference-day-1/&quot;&gt;develishdevelop&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Für mich waren folgende Vorträge am interessantesten:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/mittie&quot;&gt;Dierk König&lt;/a&gt; &amp;quot;&lt;a href=&quot;https://www.doag.org/konferenz/konferenzplaner/konferenzplaner_details.php?id=499959&amp;amp;locS=0&amp;amp;vid=509525&quot;&gt;Fun in GroovyLand&lt;/a&gt;&amp;quot;: Wie Tobias schon geschrieben hat, super Vortragsstil trotz ausgefallener Technik. Und @canonical + @builder haben sich bei mir als nützliche Annotation eingeprägt&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/danielgrycman&quot;&gt;Daniel Grycman&lt;/a&gt; &amp;quot;&lt;a href=&quot;https://www.doag.org/konferenz/konferenzplaner/konferenzplaner_details.php?id=499959&amp;amp;locS=0&amp;amp;vid=509701&quot;&gt;Introduction to Agile Documentation&lt;/a&gt;&amp;quot;: selbst noch nicht gesehen, soll aber gut gewesen sein, da AsciiDoc ;-)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/mrhaki&quot;&gt;MrHaki&lt;/a&gt; &amp;quot;&lt;a href=&quot;https://www.doag.org/konferenz/konferenzplaner/konferenzplaner_details.php?id=499959&amp;amp;locS=0&amp;amp;vid=509825&quot;&gt;Writing Documentation with Asciidoctor Is Awesome&lt;/a&gt;&amp;quot;: Toller Vortragsstil mit Live-Coding über ein langes Asciidoc-Dokument&lt;/li&gt;
&lt;li&gt;Andreas Knuth &amp;quot;&lt;a href=&quot;https://www.doag.org/konferenz/konferenzplaner/konferenzplaner_details.php?id=499959&amp;amp;locS=0&amp;amp;vid=509726&quot;&gt;PhantomJS - Schweizer Taschenmesser der WWW-Automatisierung&lt;/a&gt;&amp;quot;: Interessante Einblicke über die unter PhantomJS liegende Technologie und warum wir &lt;a href=&quot;https://github.com/KDAB/phantomjs-cef&quot;&gt;PhantomJS-CEF&lt;/a&gt; brauchen.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/goldstift&quot;&gt;Alexander Heusingfeld&lt;/a&gt; und &lt;a href=&quot;https://twitter.com/taval&quot;&gt;Tammo van Lessen&lt;/a&gt; &amp;quot;&lt;a href=&quot;https://www.doag.org/konferenz/konferenzplaner/konferenzplaner_details.php?id=499959&amp;amp;locS=0&amp;amp;vid=509488&quot;&gt;When Microservices Meet Real-World Projects: Lessons Learned&lt;/a&gt;&amp;quot;: Super Tipps und eine Leand-Deployment-Pipeline (Pull statt Push!) -&amp;gt; &lt;a href=&quot;https://www.innoq.com/en/talks/2016/03/javaland-2016-microservices-lessons-learned/&quot;&gt;Slides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/madmas&quot;&gt;Markus Schlichting&lt;/a&gt; &amp;quot;&lt;a href=&quot;https://www.doag.org/konferenz/konferenzplaner/konferenzplaner_details.php?id=499959&amp;amp;locS=0&amp;amp;vid=509841&quot;&gt;Token statt Cookies dank JWT&lt;/a&gt;&amp;quot;: genau, was ich gesucht habe, um meine JSESSIONID los zu werden! -&amp;gt; &lt;a href=&quot;https://github.com/madmas/TokenVsCookies/tree/JavaLand2016&quot;&gt;Slides&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;de&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Lots of people interested in Testing with Spock and Geb with &lt;a href=&quot;https://twitter.com/tokraft&quot;&gt;@tokraft&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/RalfDMueller&quot;&gt;@RalfDMueller&lt;/a&gt; at &lt;a href=&quot;https://twitter.com/hashtag/JavaLand?src=hash&quot;&gt;#JavaLand&lt;/a&gt; &lt;a href=&quot;https://t.co/f7XBxrNHCl&quot;&gt;pic.twitter.com/f7XBxrNHCl&lt;/a&gt;&lt;/p&gt;&amp;mdash; Florian Hopf (@fhopf) &lt;a href=&quot;https://twitter.com/fhopf/status/707185245066547200&quot;&gt;8. März 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;&lt;/td&gt;
&lt;td&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;de&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Testing automated with &lt;a href=&quot;https://twitter.com/hashtag/Selenium?src=hash&quot;&gt;#Selenium&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/WebDriver?src=hash&quot;&gt;#WebDriver&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/hashtag/Geb?src=hash&quot;&gt;#Geb&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/hashtag/Spock?src=hash&quot;&gt;#Spock&lt;/a&gt; demonstrated by &lt;a href=&quot;https://twitter.com/tokraft&quot;&gt;@tokraft&lt;/a&gt; at &lt;a href=&quot;https://twitter.com/hashtag/JavaLandConf?src=hash&quot;&gt;#JavaLandConf&lt;/a&gt; 👌 &lt;a href=&quot;https://t.co/ssQBhCjtNj&quot;&gt;pic.twitter.com/ssQBhCjtNj&lt;/a&gt;&lt;/p&gt;&amp;mdash; Markus ★ (@madmas) &lt;a href=&quot;https://twitter.com/madmas/status/707181204261486592&quot;&gt;8. März 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;3e2e77dd039b45879579a7b6895e5203&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;Wer den Vortrag verpasst hat, kann sich das Video vom Entwicklertag letzten Jahres nochmal ansehen:&lt;/p&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot;  src=&quot;https://www.youtube.com/embed/L75DdPon5Gk&quot; width=&quot;720&quot; height=&quot;480&quot;&gt;&lt;/iframe&gt;

	  </description>
    </item>
    
    <item>
      <title>Domain Class Diagrams for Grails Projects</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-8-14-Domain-Class-Diagrams-for-Grails.html</link>
      <pubDate>Fri, 14 Aug 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-8-14-Domain-Class-Diagrams-for-Grails.html</guid>
      <description>
      &lt;p&gt;A Grails project can quickly grow into larger applications. In order to still keep an overview, some architecture documentation is quite useful. One of the most useful diagrams to dive into an application is the domain class diagrams which shows you how your business or domain object interact.&lt;/p&gt;
&lt;p&gt;There are a lot of tools on the market which let you analyze and reverse engineer your project in order to draw such a class diagram. They fall in two categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tools which automatically create and layout your diagram&lt;/li&gt;
&lt;li&gt;Tools which let you manually enhance the diagram after discovering your classes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the first category, there are some Grails plugins which use tools like PlantUML to draw the needed diagrams right from within the Grails framework. That&apos;s great to get a quick overview, but since you can&apos;t easily enhance the diagrams with additional information or lay out the elements with your wisdom, I don&apos;t like them to create my project documentation.&lt;/p&gt;
&lt;p&gt;There are great tools within the second categroy, but unfortunately, I am not aware of a single one which is capable of doing the trick for Groovy classes - only Java ones. Some of them are highly configurable and it would be possible to teach them how to work with Groovy. But the effort to do so is high. For Enterprise Architect by Sparx Systems, you need Groovy descirbe as EBNF - I am currently not aware of an EBNF description and it would be hard to create and maintain one by myself.&lt;/p&gt;
&lt;p&gt;So what to do? Groovy already looks like Java and Grails knows about its domain classes. So my approach is to use a script which takes the knowledge about the domain classes available within grails and creates Java classes from it.&lt;/p&gt;
&lt;p&gt;These classes then can be easily fed into whatever UML tool you chose. As Result, you will have&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an easy way to export and synchronize your Grails domain classes to any UML tool capable of analyzing Java sources&lt;/li&gt;
&lt;li&gt;depending on you Tool, you are free to manually add your knowledge and lay out the diagrams as you like&lt;/li&gt;
&lt;li&gt;most tools keep your manual layout and additions even when you re-synchronize the diagrams with your code&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Details of the Solution&lt;/h2&gt;
&lt;p&gt;As already mentioned, I use the information already available in Grails. In order to do so, I wrote a Grails script which is invoked from the command line. The following Gist shows you the code.&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/rdmueller/acee3a5db5ea3273652b.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;Unfortunately, Grails only knows about the code, not the comments which are available within the source. So I added a little dirty hack which fetches the source of the domain class and extracts the first comment - hopefully the description of the domain class - and adds it to the java sources.&lt;/p&gt;
&lt;p&gt;In order to make it even more convenient, you can check out your UML-Tool and see if it let&apos;s you automate the synchronisation with your generated code.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Here is an example diagram for the &lt;a href=&quot;https://github.com/grails-samples/grails-petclinic&quot;&gt;Grails PetClinic sample application&lt;/a&gt; created with &lt;a href=&quot;http://sparxsystems.com/&quot;&gt;Enterprise Architect&lt;/a&gt;.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/petclinic.png&quot; style=&quot;max-width:100%;&quot; /&gt;
&lt;/div&gt;

	  </description>
    </item>
    
    <item>
      <title>Spock-Reports for Grails 2.5</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-7-16-Spock-Reports-with-Grails-2.5.html</link>
      <pubDate>Thu, 16 Jul 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-7-16-Spock-Reports-with-Grails-2.5.html</guid>
      <description>
      &lt;p&gt;In two previous posts (&lt;a href=&quot;https://rdmueller.github.io/Spock-Reports-with-Grails-3.0/&quot;&gt;Grails3.0&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://rdmueller.github.io/Spock-Reports-with-Grails-2.2/&quot;&gt;Grails2.2&lt;/a&gt;) I described how to use &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports&quot;&gt;Spock-Reports&lt;/a&gt; with &lt;a href=&quot;http://www.grails.org&quot;&gt;Grails 3.0&lt;/a&gt; and Grails 2.2.&lt;/p&gt;
&lt;p&gt;Now, if you try to use it with Grails 2.5, it seems not to work from the start. The main problem I noticed was that even&lt;br /&gt;
when I run a trivial app and all spock tests are auto-created, I got an error message at the end of the tests:&lt;br /&gt;
&lt;a href=&quot;http://stackoverflow.com/questions/31440381/forked-grails-vm-exited-with-error-while-running-test-app#comment50863764_31440381&quot;&gt;http://stackoverflow.com/questions/31440381/forked-grails-vm-exited-with-error-while-running-test-app#comment50863764_31440381&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So I tried to get rid of this error message by not forking the VM when running tests. To do that, simply set the fork-configuration&lt;br /&gt;
to &lt;code&gt;false&lt;/code&gt; for the test environments (in &lt;code&gt;BuildConfig.groovy&lt;/code&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;grails.project.fork = [
    ...
    test: false,
    ...
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, the rest seems to work the same as with Grails 2.2.4 with the only difference that Grails 2.5 uses Spock out of the box.&lt;br /&gt;
So we don&apos;t habe to configure it:&lt;/p&gt;
&lt;p&gt;just open your &lt;code&gt;grails-app/conf/BuildConfig.groovy&lt;/code&gt; file and add&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;repositories {
  [...]
  //for spock-reports
  mavenRepo &amp;quot;http://jcenter.bintray.com&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;repositories&lt;/code&gt; section and&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;dependencies {
  [...]
  //for spock-reports
  test &apos;com.athaydes:spock-reports:1.2.5&apos;  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;dependencies&lt;/code&gt; section.&lt;/p&gt;
&lt;p&gt;The standard reports are now generated and stored in &lt;code&gt;build/spock-reports/.&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Customizing your Reports&lt;/h3&gt;
&lt;p&gt;In order to store the generated reports in &lt;code&gt;target/test-reports/spock/.&lt;/code&gt; you have to customize your reports as described in the &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports#customizing-the-reports&quot;&gt;documentation&lt;/a&gt;, you have to create a file called &lt;code&gt;META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties&lt;/code&gt;.&lt;br /&gt;
That sounds easier than it is, because it has to be in the classpath and for some Grails projects, it&apos;s not easy to find the right folder to put it.&lt;/p&gt;
&lt;p&gt;For Grails 2.5, you will succeed by putting it in &lt;code&gt;grails-app/conf/META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is a sample file which uses the template based reports:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;# Name of the implementation class of the report creator
# Currently supported classes are:
#   1. com.athaydes.spockframework.report.internal.HtmlReportCreator
#   2. com.athaydes.spockframework.report.template.TemplateReportCreator
com.athaydes.spockframework.report.IReportCreator=com.athaydes.spockframework.report.template.TemplateReportCreator

# Output directory (where the spock reports will be created) - relative to working directory
com.athaydes.spockframework.report.outputDir=target/test-reports/spock

# If set to true, hides blocks which do not have any description
com.athaydes.spockframework.report.hideEmptyBlocks=false

# Set properties of the report creator
com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile=/spockreporttemplate/spec-template.md
com.athaydes.spockframework.report.template.TemplateReportCreator.reportFileExtension=md
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryTemplateFile=/spockreporttemplate/summary-template.md
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryFileName=summary.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;this file specifies that the templates are located in &lt;code&gt;grails-app/conf/spockreporttemplates&lt;/code&gt; and the output&lt;br /&gt;
will be written to &lt;code&gt;target/test-reports/spock&lt;/code&gt;. A good idea is to start with the default templates &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports/blob/master/src/main/resources/templateReportCreator/spec-template.md&quot;&gt;spec-template.md&lt;/a&gt; and &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports/blob/master/src/main/resources/templateReportCreator/summary-template.md&quot;&gt;summary-template.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You might want to use this &lt;a href=&quot;https://github.com/rdmueller/Grails2.5-Spock-Reports-Sample&quot;&gt;https://github.com/rdmueller/Grails2.5-Spock-Reports-Sample&lt;/a&gt; as a starting point...&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Spock-Reports for Grails 2.2</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-7-14-Spock-Reports-with-Grails-2.2.html</link>
      <pubDate>Tue, 14 Jul 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-7-14-Spock-Reports-with-Grails-2.2.html</guid>
      <description>
      &lt;p&gt;In a &lt;a href=&quot;https://rdmueller.github.io/Spock-Reports-with-Grails-3.0/&quot;&gt;previous post&lt;/a&gt; I described how to use &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports&quot;&gt;Spock-Reports&lt;/a&gt; with &lt;a href=&quot;http://www.grails.org&quot;&gt;Grails 3.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That was easy since Grails 3.0 is Gradle based.&lt;/p&gt;
&lt;p&gt;Now I will try to figure out how to use Spock-Reports with Grails 2.2.4 .&lt;/p&gt;
&lt;p&gt;Again, the configuration of the dependencies is easy: just open your &lt;code&gt;grails-app/conf/BuildConfig.groovy&lt;/code&gt; file and add&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;repositories {
  [...]
  //for spock-reports
  mavenRepo &amp;quot;http://jcenter.bintray.com&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;repositories&lt;/code&gt; section and&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;dependencies {
  [...]
  //for spock-reports
  test &apos;com.athaydes:spock-reports:1.2.5&apos;  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;dependencies&lt;/code&gt; section. But since Grails 2.2.4 does not include Spock be default, we also have to follow the&lt;br /&gt;
&lt;a href=&quot;https://grails.org/plugin/spock&quot;&gt;documentation for the Grails-Spock-Plugin&lt;/a&gt; and add in addition&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;plugins {
  [...]
	test(&amp;quot;:spock:0.7&amp;quot;) {
	    //since we use groovy 2.x with grails 2.2.4
      	    exclude &amp;quot;spock-grails-support&amp;quot;
    	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the plugins section and&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;dependencies {
  [...]
  test &apos;org.spockframework:spock-grails-support:0.7-groovy-2.0&apos;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the dependencies section. Now, that should do the trick. The standard reports are now generated and stored in &lt;code&gt;build/spock-reports/.&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Customizing your Reports&lt;/h3&gt;
&lt;p&gt;In order to store the generated reports in &lt;code&gt;target/test-reports/spock/.&lt;/code&gt; you have to customize your reports as described in the &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports#customizing-the-reports&quot;&gt;documentation&lt;/a&gt;, you have to create a file called &lt;code&gt;META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties&lt;/code&gt;.&lt;br /&gt;
That sounds easier than it is, because it has to be in the classpath and for some Grails projects, it&apos;s not easy to find the right folder to put it.&lt;/p&gt;
&lt;p&gt;For Grails 2.2.4, you will succeed by putting it in &lt;code&gt;grails-app/conf/META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is a sample file which uses the template based reports:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;# Name of the implementation class of the report creator
# Currently supported classes are:
#   1. com.athaydes.spockframework.report.internal.HtmlReportCreator
#   2. com.athaydes.spockframework.report.template.TemplateReportCreator
com.athaydes.spockframework.report.IReportCreator=com.athaydes.spockframework.report.template.TemplateReportCreator

# Output directory (where the spock reports will be created) - relative to working directory
com.athaydes.spockframework.report.outputDir=target/test-reports/spock

# If set to true, hides blocks which do not have any description
com.athaydes.spockframework.report.hideEmptyBlocks=false

# Set properties of the report creator
com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile=/spockreporttemplate/spec-template.md
com.athaydes.spockframework.report.template.TemplateReportCreator.reportFileExtension=md
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryTemplateFile=/spockreporttemplate/summary-template.md
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryFileName=summary.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;this file specifies that the templates are located in &lt;code&gt;grails-app/conf/spockreporttemplates&lt;/code&gt; and the output&lt;br /&gt;
will be written to &lt;code&gt;target/test-reports/spock&lt;/code&gt;. A good idea is to start with the default templates &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports/blob/master/src/main/resources/templateReportCreator/spec-template.md&quot;&gt;spec-template.md&lt;/a&gt; and &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports/blob/master/src/main/resources/templateReportCreator/summary-template.md&quot;&gt;summary-template.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You might want to use this &lt;a href=&quot;https://github.com/rdmueller/Grails2.2-Spock-Reports-Sample&quot;&gt;https://github.com/rdmueller/Grails2.2-Spock-Reports-Sample&lt;/a&gt; as a starting point...&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>A Fool with a Tool is still a Fool...</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-7-12-A-Fool-with-a-Tool-1.html</link>
      <pubDate>Sun, 12 Jul 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-7-12-A-Fool-with-a-Tool-1.html</guid>
      <description>
      &lt;p&gt;...but sometimes the tool makes a difference!&lt;/p&gt;
&lt;p&gt;I just came back from an interesting 3 day workshop on which I had a first&lt;br /&gt;
chance to make use of my drawing equipment I bought recently. Originally, I wanted to draw some slides for my talk at&lt;br /&gt;
&lt;a href=&quot;https://rdmueller.github.io/etka/&quot;&gt;Entwicklertag Karlsruhe&lt;/a&gt; but we later dropped the idea in favour of professional clip art.&lt;/p&gt;
&lt;p&gt;But since we&apos;ve had a flip chart available at the workshop and I thought that creating power point slides would take too much&lt;br /&gt;
time when only 3 days are available, I gave it a try:&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/bikablo-Example.png&quot; style=&quot;width:100%;&quot; /&gt;
&lt;span style=&quot;font-size: smaller;&quot;&gt;Diese Abbildung wurde inspiriert durch die bikablo® Publikationen, www.kommunikationslotsen.de&lt;/span&gt;
&lt;/div&gt;
I used my [neuland &quot;fine One&quot; set of artmarkers](http://de.neuland.com/marker-und-stifte/neuland-marker/fineone-by-neuland-artmarker-pinselpitze-13er-farbset.html?c=725) 
and my [bikablo-books](http://bikablo.kommunikationslotsen.de/bikablo-produkte/) with lot&apos;s of ideas on how to visualize ideas and then started to draw. The feedback I&apos;ve got was great!
&lt;p&gt;The &amp;quot;fine One&amp;quot; markers are not the best for a flip chart - they are designed for smaller format, but the do work on larger formats too.&lt;br /&gt;
The brush tip gives your drawings a professional look which is visibly different from standard flip chart markers. The different light colors enable you to colorize your visualisations and give them the finishing touch.&lt;/p&gt;
&lt;p&gt;Btw: after I had my first results with the artmarkers, I bought myself a Wacom Intuos drawing tablet (&lt;a href=&quot;http://www.wacom.com/en-gb/products/pen-tablets/intuos-pen-and-touch-small&quot;&gt;CTH-480&lt;/a&gt;) and searched for good and affordable drawing software to recrate the effects I created with the artmakers. I found &lt;a href=&quot;https://inkscape.org/&quot;&gt;InkScape&lt;/a&gt; to be the most convenient and free tool. This is the result:&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img src=&quot;../images/bikablo-Example-tablet.png&quot; style=&quot;width:100%;&quot; /&gt;
&lt;span style=&quot;font-size: smaller;&quot;&gt;Diese Abbildung wurde inspiriert durch die bikablo® Publikationen, www.kommunikationslotsen.de&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;If you have any hints on how to get better results (I guess there is better software :-) please tell me!&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Spock-Reports for Grails 3.0</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-7-11-Spock-Reports-with-Grails-3.0.html</link>
      <pubDate>Sat, 11 Jul 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-7-11-Spock-Reports-with-Grails-3.0.html</guid>
      <description>
      &lt;p&gt;&lt;a href=&quot;https://github.com/renatoathaydes/spock-reports&quot;&gt;Spock-Reports&lt;/a&gt; is a great way to create better reports for &lt;a href=&quot;https://github.com/spockframework/spock&quot;&gt;Spock&lt;/a&gt;.&lt;/p&gt;
&lt;!--more--&gt;
&lt;!--more--&gt;&lt;!--more--&gt;&lt;!--more--&gt;&lt;!--more--&gt;&lt;!--more--&gt;&lt;!--more--&gt;
&lt;p&gt;Since Grails 3.0 is based on Gradle, integrating the Spock-Reports is easy. Just open your &lt;code&gt;build.gradle&lt;/code&gt; file and add&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;repositories {
  [...]
  //for spock-reports
  jcenter()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;repositories&lt;/code&gt; section and&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;dependencies {
  [...]
  //for spock-reports
  testCompile &apos;com.athaydes:spock-reports:1.2.5&apos;  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;dependencies&lt;/code&gt; section.&lt;/p&gt;
&lt;p&gt;that&apos;s it... The next time you run &lt;code&gt;grails test-app&lt;/code&gt;, you&apos;ll find the generated Spock-Reports in &lt;code&gt;/build/spock-reports/&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Customizing your Reports&lt;/h3&gt;
&lt;p&gt;If you want to customize your reports as described in the &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports#customizing-the-reports&quot;&gt;documentation&lt;/a&gt;, you have to create a file called &lt;code&gt;META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties&lt;/code&gt;. That sounds easier than it is, because it has to be in the classpath and for some Grails projects, it&apos;s not easy to find the right folder to put it.&lt;/p&gt;
&lt;p&gt;For Grails 3.0, you will succeed by putting it in &lt;code&gt;src/test/resources/META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is a sample file which uses the template based reports:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;# Name of the implementation class of the report creator
# Currently supported classes are:
#   1. com.athaydes.spockframework.report.internal.HtmlReportCreator
#   2. com.athaydes.spockframework.report.template.TemplateReportCreator
com.athaydes.spockframework.report.IReportCreator=com.athaydes.spockframework.report.template.TemplateReportCreator

# Output directory (where the spock reports will be created) - relative to working directory
com.athaydes.spockframework.report.outputDir=build/spock-reports-mds

# If set to true, hides blocks which do not have any description
com.athaydes.spockframework.report.hideEmptyBlocks=false

# Set properties of the report creator
com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile=/spockreporttemplate/spec-template.md
com.athaydes.spockframework.report.template.TemplateReportCreator.reportFileExtension=md
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryTemplateFile=/spockreporttemplate/summary-template.md
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryFileName=summary.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;this file specifies that the templates are located in &lt;code&gt;src/test/resources/spockreporttemplates&lt;/code&gt;. A good idea is to start with the default templates &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports/blob/master/src/main/resources/templateReportCreator/spec-template.md&quot;&gt;spec-template.md&lt;/a&gt; and &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports/blob/master/src/main/resources/templateReportCreator/summary-template.md&quot;&gt;summary-template.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You might want to use this &lt;a href=&quot;https://github.com/rdmueller/Grails3.0-Spock-Reports-Sample&quot;&gt;https://github.com/rdmueller/Grails3.0-Spock-Reports-Sample&lt;/a&gt; as a starting point...&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Spock und Geb - Übersichtlich und nachvollziehbar Testen für alle!</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-7-5-etka.html</link>
      <pubDate>Sun, 5 Jul 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-7-5-etka.html</guid>
      <description>
      &lt;p&gt;Auf dem Entwicklertag Karlsruhe hatte ich zusammen mit Tobias Kraft mal wieder die Möglichkeit meine Ideen in einem Vortrag&lt;br /&gt;
zu präsentieren. Mittlerweile ist sogar das Video zum &lt;a href=&quot;https://entwicklertag.de/karlsruhe/2015/spock-und-geb-bersichtlich-und-nachvollziehbar-testen-f-r-alle&quot;&gt;Vortrag&lt;/a&gt; online.&lt;/p&gt;
&lt;p&gt;In dem Vortrag geht es darum, wie man bei der Entwicklung einer webbasierten Anwendung zusammen mit dem Kunden (Product Owner) eine &amp;quot;Testfahrt&amp;quot; der Applikation planen, automatisch ausführen und einen aussagekräftigen Report erstellen kann.&lt;/p&gt;
&lt;p&gt;Viel Spass beim ansehen!&lt;/p&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot;  src=&quot;https://www.youtube.com/embed/L75DdPon5Gk&quot; width=&quot;720&quot; height=&quot;480&quot;&gt;&lt;/iframe&gt;
&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;a5e3259364ba4c1dafc4a89890209bf2&quot; data-ratio=&quot;1.41436464088398&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;

	  </description>
    </item>
    
    <item>
      <title>Spock-Reports with Templates</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-3-15-spock-report-templates.html</link>
      <pubDate>Sun, 15 Mar 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-3-15-spock-report-templates.html</guid>
      <description>
      &lt;p&gt;The new template engine for the Spock-Reports-Plugin is out. Let&apos;s build an asciidoc template with it.&lt;/p&gt;
&lt;h3&gt;Step 1: configure the plugin&lt;/h3&gt;
&lt;p&gt;Renato describes this step in detail on the &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports&quot;&gt;Plugin Homepage&lt;/a&gt;. I&apos;ve placed the properties file in &lt;code&gt;src/test/resources/main/META-INF/services/&lt;/code&gt; and so I place my templates also in &lt;code&gt;src/test/resources/spockreporttemplate/&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;com.athaydes.spockframework.report.template.TemplateReportCreator.specTemplateFile=/spockreporttemplate/spec-template.ad
com.athaydes.spockframework.report.template.TemplateReportCreator.reportFileExtension=ad
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryTemplateFile=/spockreporttemplate/summary-template.ad
com.athaydes.spockframework.report.template.TemplateReportCreator.summaryFileName=summary.ad
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just to get started, I placed two emtpy files &lt;code&gt;spec-template.ad&lt;/code&gt; and &lt;code&gt;summary-template.ad&lt;/code&gt; at the right location and ran my tests just to see that those empty templates are picked up.&lt;/p&gt;
&lt;h3&gt;Step 2: create a summary template&lt;/h3&gt;
&lt;p&gt;I&apos;ll start with the summary report. It seems to be the easier one. Renato already provided a &lt;a href=&quot;https://raw.githubusercontent.com/renatoathaydes/spock-reports/master/src/main/resources/templateReportCreator/summary-template.md&quot;&gt;markdown sample&lt;/a&gt;, so let&apos;s take a look at it to see the data which is available to the template.&lt;/p&gt;
&lt;p&gt;So it seems that we have a convinience function (&lt;code&gt;aggregateStats&lt;/code&gt;) which creates some statistical data about our test runs and the &lt;code&gt;data&lt;/code&gt; object itself.&lt;/p&gt;
&lt;p&gt;Let&apos;s modify the empty template in order to output both data structures:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;&amp;lt;% def stats = com.athaydes.spockframework.report.util.Utils.aggregateStats( data ) %&amp;gt;
${stats.inspect()}
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
${data.inspect()}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which leads to the following output: (a little bit reformatted for better readability)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;[&apos;total&apos;:13, &apos;passed&apos;:13, &apos;failed&apos;:0, &apos;fFails&apos;:0, &apos;fErrors&apos;:0, &apos;time&apos;:258.0, &apos;successRate&apos;:1.0]
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;
[&apos;DatabaseDrivenSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:1, &apos;successRate&apos;:1.0, &apos;time&apos;:67], 
	&apos;DataDrivenSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:3, &apos;successRate&apos;:1.0, &apos;time&apos;:19], 
	&apos;DerivedSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:2, &apos;successRate&apos;:1.0, &apos;time&apos;:16], 
	&apos;EmptyStackSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:4, &apos;successRate&apos;:1.0, &apos;time&apos;:20], 
	&apos;HamcrestMatchersSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:1, &apos;successRate&apos;:1.0, &apos;time&apos;:21], 
	&apos;HelloSpockSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:1, &apos;successRate&apos;:1.0, &apos;time&apos;:3], 
	&apos;IncludeExcludeExtensionSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:3, &apos;successRate&apos;:1.0, &apos;time&apos;:3], 
	&apos;OrderedInteractionsSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:1, &apos;successRate&apos;:1.0, &apos;time&apos;:49], 
	&apos;PublisherSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:2, &apos;successRate&apos;:1.0, &apos;time&apos;:24], 
	&apos;StackWithOneElementSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:4, &apos;successRate&apos;:1.0, &apos;time&apos;:4], 
	&apos;StackWithThreeElementsSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:4, &apos;successRate&apos;:1.0, &apos;time&apos;:7], 
	&apos;StepwiseExtensionSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:3, &apos;successRate&apos;:1.0, &apos;time&apos;:4], 
	&apos;UsingJUnitRulesSpec&apos;:[&apos;failures&apos;:0, &apos;errors&apos;:0, &apos;skipped&apos;:0, &apos;totalRuns&apos;:1, &apos;successRate&apos;:1.0, &apos;time&apos;:21]
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&apos;s great! We get hashmaps which can be easily inspected. That will make it even easier to write a template.&lt;/p&gt;
&lt;p&gt;Now let&apos;s come up with the real template:&lt;/p&gt;
&lt;h4&gt;summary-template.ad:&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;&amp;lt;% def stats = com.athaydes.spockframework.report.util.Utils.aggregateStats( data )
 %&amp;gt;= Specification run results

== Specifications summary

[small&amp;gt;#created on ${new Date()} by ${System.properties[&apos;user.name&apos;]}#

.summary
[options=&amp;quot;header&amp;quot;]
|==================================================================================================================================
| Total          | Passed          | Failed          | Feature failures | Feature errors   | Success rate        | Total time (ms) 
| ${stats.total} | ${stats.passed} | ${stats.failed} | ${stats.fFails}  | ${stats.fErrors} | ${stats.successRate}| ${stats.time}   
|==================================================================================================================================

== Specifications

[options=&amp;quot;header&amp;quot;]
|===================================================================
|Name  | Features | Failed | Errors | Skipped | Success rate | Time 
&amp;lt;% data.each { name, map -&amp;gt;
 %&amp;gt;| $name | ${map.totalRuns} | ${map.failures} | ${map.errors} | ${map.skipped} | ${map.successRate} | ${map.time} 
&amp;lt;% } %&amp;gt;
|===================================================================

[small]#generated by ${com.athaydes.spockframework.report.SpockReportExtension.PROJECT_URL}[Athaydes Spock Reports]#
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since MarkDown and AsciiDoc do not differ too much for this template, this was easy! Details regarding the formatting can be solved later...&lt;/p&gt;
&lt;p&gt;To check the correct asciidoc syntax, you can simply copy and paste the result to the asciidoc live editor &lt;a href=&quot;https://asciidoclive.com/&quot;&gt;https://asciidoclive.com/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Step 3: create a spec template&lt;/h3&gt;
&lt;p&gt;Now let&apos;s do the same with the spec template. First try to figure out what data we will have available.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;${data.dump()}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but this time, the dump does not give us such a good result: (reformatted for readability)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;&amp;lt;com.athaydes.spockframework.report.internal.SpecData@5de17399 
info=org.spockframework.runtime.model.SpecInfo@7c6c71f5
featureRuns=[
	com.athaydes.spockframework.report.internal.FeatureRun@33adcba4,
	com.athaydes.spockframework.report.internal.FeatureRun@5714967d,
	com.athaydes.spockframework.report.internal.FeatureRun@8a41535
	] 
totalTime=10&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can only see the different java object within the dump and not the full data structure. Since I don&apos;t like to go to the source of those structure and analyze it, I now take the MarkDown sample template and start to transform it right away. This should lead to a solution which will fit for the moment:&lt;/p&gt;
&lt;h4&gt;spec-template.ad:&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;&amp;lt;%  def fmt = new com.athaydes.spockframework.report.internal.StringFormatHelper()
    def stats = com.athaydes.spockframework.report.util.Utils.stats( data )
 %&amp;gt;== Report for ${data.info.description.className}

=== Summary

[cols=&amp;quot;asciidoc,asciidoc&amp;quot;]
|====
|* Total Runs: ${stats.totalRuns}
 * Success Rate: ${fmt.toPercentage(stats.successRate)}
 * Total time: ${fmt.toTimeDuration(stats.time)}
|* Failures: ${stats.failures}
 * Errors:   ${stats.errors}
 * Skipped:  ${stats.skipped}
|====

=== Features
&amp;lt;%
    features.forEach { name, result, blocks, iterations, params -&amp;gt;
%&amp;gt;
==== $name

Result: **$result**
&amp;lt;%
        for ( block in blocks ) {
 %&amp;gt;
* ${block.kind} ${block.text}
&amp;lt;%
        }
        def executedIterations = iterations.findAll { it.dataValues || it.errors }
        if ( params &amp;amp;&amp;amp; executedIterations ) {
 %&amp;gt;
[options=&amp;quot;header&amp;quot;]
|====
| ${params.join( &apos; | &apos; )} |
&amp;lt;%
            for ( iteration in executedIterations ) {
%&amp;gt;| ${iteration.dataValues.join( &apos; | &apos; )} | ${iteration.errors ? &apos;(FAIL)&apos; : &apos;(PASS)&apos;}
&amp;lt;%          } 
%&amp;gt;|====
&amp;lt;%      }
        def problems = executedIterations.findAll { it.errors }
        if ( problems ) {
            out &amp;lt;&amp;lt; &amp;quot;\nThe following problems occurred:\n\n&amp;quot;
            for ( badIteration in problems ) {
                if ( badIteration.dataValues ) {
                    out &amp;lt;&amp;lt; &apos;* &apos; &amp;lt;&amp;lt; badIteration.dataValues &amp;lt;&amp;lt; &apos;\n&apos;
                }
                for ( error in badIteration.errors ) {
                    out &amp;lt;&amp;lt; &apos;----\n&apos; &amp;lt;&amp;lt; error &amp;lt;&amp;lt; &apos;\n----\n&apos;
                }
            }
        }
    }
 %&amp;gt;

[small]#generated by ${com.athaydes.spockframework.report.SpockReportExtension.PROJECT_URL}[Athaydes Spock Reports]#
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result looks good :-) Now that we have the summary report and all spec reports, we can add a small section to the summary template which includes all spec reports or order to create one big report file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;&amp;lt;% data.each { name, map -&amp;gt;
 %&amp;gt;
&amp;lt;&amp;lt;&amp;lt;&amp;lt;

include::${name}.ad[]
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we only need to create a gradle task which renders it.&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>How to use the Spock-Reports-Plugin with Gradle</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-3-14-spock-reports-with-gradle.html</link>
      <pubDate>Sat, 14 Mar 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-3-14-spock-reports-with-gradle.html</guid>
      <description>
      &lt;p&gt;Since I experienced some problems when I tried to use the Spock-Reports-Plugin in Grails, I now tried to use it with Gradle.&lt;/p&gt;
&lt;p&gt;The basics are easy and well described on the &lt;a href=&quot;https://github.com/renatoathaydes/spock-reports&quot;&gt;Spock-Reports page&lt;/a&gt; - just add the needed repository and dependency to your gradle build file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-groovy&quot;&gt;    ...
    repositories {
        ...
        jcenter()
    }
    ...

    dependencies {
        ...
        testCompile &apos;com.athaydes:spock-reports:1.2.5&apos;
    }
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But where to place the properties file in case you want to modify some of them (for instance switch to the new template report engine)? Renato just writes that you should copy the properties &lt;em&gt;&amp;quot;to a file at &lt;code&gt;META-INF/services/com.athaydes.spockframework.report.IReportCreator.properties&lt;/code&gt; relative to the classpath&amp;quot;&lt;/em&gt;. Since I am a Gradle newbie, I had to do some experiments before I found out that one place where you can put it is the same as for maven: &lt;code&gt;src/test/resources/&lt;/code&gt;. And &lt;code&gt;src/main/resources/&lt;/code&gt; will also work.&lt;/p&gt;

	  </description>
    </item>
    
    <item>
      <title>Starting a new Blog</title>
      <link>https://fiveandahalfstars.ninja/blog/2015/2015-3-3-starting-a-blog.html</link>
      <pubDate>Tue, 3 Mar 2015 00:00:00 +0000</pubDate>
      <guid isPermaLink="false">blog/2015/2015-3-3-starting-a-blog.html</guid>
      <description>
      &lt;p&gt;Just started my new blog. I&apos;ve already had several blogs with more or less success, so why do I now start another? First of all because I don&apos;t what to be a ghost developer.&lt;/p&gt;

	  </description>
    </item>
    

  </channel> 
</rss>
