<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  
  <title>routeralle</title>
  <subtitle>Notes from a geeks life.</subtitle>
  <link href="https://routeralle.se/feed.xml" rel="self" />
  <link href="https://routeralle.se/" />
  <updated>2026-08-10T00:00:00Z</updated>
  <id>https://routeralle.se/</id>
  <author>
    <name>Rasmus Karlsson</name>
    <email>rasmus@routeralle.se</email>
  </author>
  <entry>
    <title>DEVASC: Jämför olika dataformat (XML, JSON, YAML)</title>
    <link href="https://routeralle.se/2022/jamfor-olika-dataformat-xml-json-yaml/" />
    <updated>2022-06-16T00:00:00Z</updated>
    <id>https://routeralle.se/2022/jamfor-olika-dataformat-xml-json-yaml/</id>
    <content type="html">&lt;h2&gt;XML&lt;/h2&gt;
&lt;p&gt;“Extensible Markup Language” (XML) är ett textbaserat märkspråk som används för att representera strukturerad information. Språket är plattformsneutralt.&lt;/p&gt;
&lt;p&gt;Någon som tidigare har skrivit HTML kan se likheter i strukturen med taggar, attribut och element. Här nedan ser vi hur XML data kan se ut:&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;device&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;hostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;LAB01&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;hostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ipv6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;FE80::903A:1C1A:E802:11E4&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ipv6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;online&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;device&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Den första raden i koden ovan kallas för &lt;strong&gt;prolog&lt;/strong&gt;. I denna definierar vi XML version och teckenkodningsattribut.&lt;/p&gt;
&lt;p&gt;Efter prologen har vi kroppen (“body”). XML kroppen innehåller våra taggar som är &lt;strong&gt;element&lt;/strong&gt; för data. Vi namnger själva våra element och kan skapa dessa på 4 olika sätt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ett tomt element:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Ett element utan innehåll:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Ett element med innehåll:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Vi lär oss!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Ett element kan även ha attribut:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tag&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;myAttribute&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;XML är väldigt verbalt och enkelt för oss människor att förstå. Det har däremot sina nackdelar, det kan vara svårare att parsa XML data med skriptspråk som exempelvis Python.&lt;/p&gt;
&lt;h2&gt;JSON&lt;/h2&gt;
&lt;p&gt;“JavaScript Object Notation” (JSON) är ett lättviktigt datautbytesformat som härstammar från “object literals” i JavaScript.&lt;/p&gt;
&lt;p&gt;I följande stycke har jag skrivit om datan i XML exemplet till JSON format:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;device&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;hostname&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;LAB01&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;ipv6&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FE80::903A:1C1A:E802:11E4&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;online&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Objekten i JSON skrivs som nyckel-värde-par, de olika paren är separerade av kommatecken. Ett objekt kan ha flera par (som exemplet ovan). Datatyper för värden är heltal, strängar, boolesk eller “null” (värde utan bindning till något).&lt;/p&gt;
&lt;p&gt;Eftersom att JSON härstammar från JavaScript behöver vi inte heller tänka på någon form av indentering när vi bygger formatet, det används mestadels för mänsklig läsbarhet. Vill vi kan vi skriva datan även så här:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;device&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;hostname&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;LAB01&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;ipv6&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;FE80::903A:1C1A:E802:11E4&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;online&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Men… det är inte lika snyggt och enkelt för en människa att läsa. 🙂&lt;/p&gt;
&lt;h2&gt;YAML&lt;/h2&gt;
&lt;p&gt;“YAML Ain’t Markup Language” (YAML) är ett dataserialiseringsformat vars syntax är inspirerad av XML, med ett mål att vara lättläst för människor.&lt;/p&gt;
&lt;p&gt;Tidigare exempeldata kan skrivas som:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; LAB01
  &lt;span class=&quot;token key atrule&quot;&gt;ipv6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; FE80&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;903A&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;1C1A&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;E802&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;11E4&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; online
&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En YAML fil öppnas med tre bindestreck och stängs med tre punkter. Datan skrivs även här som nyckel-värde-par. Datatyper för värden är heltal, strängar, boolesk eller “null” (värde utan bindning till något).&lt;/p&gt;
&lt;p&gt;I YAML är det enklare att representera mer komplex data, så som en ordnad lista:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;lista&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Någonting som är viktigt i YAML är blanksteg (indentering). Utan indentering tappar vi språkets hierarki men antalet blanksteg som vi använder har ingen betydelse; det behöver däremot vara konsekvent och skapat av mellanslagstangenten.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>DEVASC: API på webben, del 1</title>
    <link href="https://routeralle.se/2022/devasc-api-pa-webben-del-1/" />
    <updated>2022-06-21T00:00:00Z</updated>
    <id>https://routeralle.se/2022/devasc-api-pa-webben-del-1/</id>
    <content type="html">&lt;p&gt;Jag vill börja detta inlägg genom att förklara 2 centrala begrepp:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;“Representational State Transfer” (REST)&lt;/strong&gt;: en arkitekturstil som sätter en standard för kommunikation mellan system på webben.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“Application Program Interface” (API)&lt;/strong&gt;: definierar ett sätt för att program, system och applikationer ska kunna prata med varandra. På en väldigt hög nivå kan vi se API som en tolk för att förflytta data från en plats till en annan.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Vad är ett REST API?&lt;/h3&gt;
&lt;p&gt;Ett REST API är byggt av fyra komponenter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;“Uniform Resource Identifier” (URI)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Identifierar en resurs och består av flera delar&lt;/li&gt;
&lt;li&gt;Ett exempel: &lt;code&gt;https://swapi.dev/api/people/1/&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https:&lt;/code&gt; definierar schemat
&lt;ul&gt;
&lt;li&gt;vilket protokoll som används&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;//swapi.dev&lt;/code&gt; definierar en “authority” komponent
&lt;ul&gt;
&lt;li&gt;adress för destination, består oftast av värdadress och port&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/people/1/&lt;/code&gt; definierar sökvägen
&lt;ul&gt;
&lt;li&gt;står för platsen som resursen finns på, likt exemplet kan den bestå av flera segment&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;om du undrar vad skillnaderna mellan URI och URL är hade jag rekommenderat att läsa mer här: &lt;a href=&quot;https://www.javatpoint.com/uri-vs-url&quot;&gt;https://www.javatpoint.com/uri-vs-url&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HTTP metod&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;REST APIer använder de vanliga HTTP metoderna. Vilka metoder som finns tillgängliga varierar mellan olika system. De vanligaste metoderna som används är:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;POST&lt;/strong&gt; – skapar en ny resurs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GET&lt;/strong&gt; – hämtar en resurs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PUT&lt;/strong&gt; – ersätt eller uppdatera en resurs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PATCH&lt;/strong&gt; – uppdatera specifika uppgifter i en resurs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DELETE&lt;/strong&gt; – radera en resurs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Header&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;En vanlig HTTP header används när vi jobbar med REST APIer. Den är valfri att använda och data formateras som nyckel-värde-par.&lt;/li&gt;
&lt;li&gt;Det finns två typer av headers:
&lt;ul&gt;
&lt;li&gt;Request Header – innehåller extra information som inte har med innehållet att göra, så som exempelvis autentisering&lt;/li&gt;
&lt;li&gt;Entity Header – innehåller information som beskriver innehållet, så som exempelvis “&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type&quot;&gt;content-type&lt;/a&gt;“&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Body&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Innehållet av en förfrågan&lt;/li&gt;
&lt;li&gt;Denna kan vara valfri, beroende på vilken HTTP metod som används. Om vi lägger till innehåll behöver vi specificera mediatypen i en entity header (med content-type).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Alla REST APIer är inte identiska, läs alltid dokumentationen för att se hur du ska använda ett API.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I nästa del labbar vi lite för att se hur det funkar i praktiken.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>DEVASC: API på webben, del 2</title>
    <link href="https://routeralle.se/2022/devasc-api-pa-webben-del-2/" />
    <updated>2022-06-21T00:00:00Z</updated>
    <id>https://routeralle.se/2022/devasc-api-pa-webben-del-2/</id>
    <content type="html">&lt;p&gt;I den &lt;a href=&quot;https://routeralle.se/2022/devasc-api-pa-webben-del-1/&quot;&gt;tidigare delen&lt;/a&gt; gick vi igenom teori över REST APIer. Nu ska vi använda Python och ett HTTP bibliotek för att prata med ett API på webben.&lt;/p&gt;
&lt;p&gt;Förutsättningar för att göra labben:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.python.org/downloads/&quot;&gt;Python3.10&lt;/a&gt; med “&lt;a href=&quot;https://pypi.org/project/requests/&quot;&gt;requests&lt;/a&gt;” biblioteket
&lt;ul&gt;
&lt;li&gt;ett bibliotek består av färdiga moduler som underlättar utvecklingen för oss, &lt;a href=&quot;https://www.geeksforgeeks.org/libraries-in-python/&quot;&gt;läs mer här&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;En &lt;a href=&quot;https://www.redhat.com/en/topics/middleware/what-is-ide&quot;&gt;IDE&lt;/a&gt; (eller textredigerare) att skriva vår kod i
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;jag använder &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Labb&lt;/h2&gt;
&lt;p&gt;I denna labb kommer vi att anropa ett &lt;a href=&quot;https://swapi.dev&quot;&gt;Star Wars API&lt;/a&gt; (SWAPI) och hämta data om Luke Skywalker. Om vi kollar på dokumentationen ser vi att SWAPI är ett öppet API (kräver ingen autentisering) och att det har ett JSON schema på sina resurser.&lt;/p&gt;
&lt;p&gt;Vi börjar koden med att importera “requests” biblioteket:&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Eftersom att vi bara ska hämta data kommer vi att använda oss av HTTP metoden “GET”. För att göra detta kommer vi använda get() metoden ur “requests”, vi sätter svaret i en variabel kallad “response” och ser även till att tolka kroppen som JSON med json() metoden:&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://swapi.dev/api/people/1/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vi avslutar vårt kodstycke med att skriva ut svaret lite snyggt i terminalen (genom att hämta värdet i utvalda nyckel-värde-par formaterat i en f-sträng):&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Name: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;name&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#92;nHeight: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;height&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; cm&#92;nGender: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;gender&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vår lilla kod kommer då att se ut på följande vis:&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; requests

response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; requests&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://swapi.dev/api/people/1/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;Name: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;name&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#92;nHeight: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;height&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; cm&#92;nGender: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;gender&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jag har valt att spara koden som en egen fil och exekverar den enligt följande, med förväntad output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rasmus@rasmus-lnx:~/dev/routeralle/restapi$ python3 luke.py
Name: Luke Skywalker
Height: 172 cm
Gender: male
&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>Cisco Modeling Labs: Cut to the chase</title>
    <link href="https://routeralle.se/2024/cisco-modeling-labs-cut-to-the-chase/" />
    <updated>2024-12-03T00:00:00Z</updated>
    <id>https://routeralle.se/2024/cisco-modeling-labs-cut-to-the-chase/</id>
    <content type="html">&lt;p&gt;For the past years I have been using EVE-NG for most of my labs. It’s been a pleasure, but I’ve always felt like something was missing when it comes to simplicity and time it takes to resolve issues from time to time. As version 2.8 of Cisco Modeling Labs (CML) featured a new free tier, I tried it and was hooked. Even though it did not bring a lot of new things to the table, it was a whole lot easier deploying and operating.&lt;/p&gt;
&lt;p&gt;During yesterdays cyber monday sale at Cisco Learning Network Store I made a decision and bought the “Personal Plus” license. I just could not resist it at 40% off and as I am approaching more demanding studies in my CCIE EI journey, it felt like a good investment. As the free tier, it was super easy to install even tough I had some troubles in mounting and getting the files from one of the refplat ISOs the natural way via cdrom on my hypervisor. Lucky for me, transferring the file using SCP to the VM was an alternative and worked as smooth as a normal cdrom mount.&lt;/p&gt;
&lt;p&gt;Looking forward to diving deeper in to the world of CML and connecting nodes to external services in my lab environment, such as DNAC and ISE. This will for sure be a game changer in doing larger mock labs for the CCIE.&lt;/p&gt;
&lt;p&gt;If you have not tried CML yet, you can &lt;a href=&quot;https://mkto.cisco.com/cml-free.html&quot;&gt;sign up here&lt;/a&gt; for the free tier, which has a 5 node limit but still allows for plenty of labbing.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Cohesion and coupling in modular programming</title>
    <link href="https://routeralle.se/2025/cohesion-and-coupling-in-modular-programming/" />
    <updated>2025-01-27T00:00:00Z</updated>
    <id>https://routeralle.se/2025/cohesion-and-coupling-in-modular-programming/</id>
    <content type="html">&lt;p&gt;In modular programming, cohesion and coupling are two fundamental concepts that play an important part in how you will organize your code. Understanding these concepts, and being able to balance them, forms the basis of any maintainable, efficient, and scalable software system. Let’s dive deeper into these concepts below.&lt;/p&gt;
&lt;h2&gt;Cohesion&lt;/h2&gt;
&lt;p&gt;Cohesion is about how well related different parts of a module are to each other. A module with high cohesion focuses on a single task or a single responsibility. This makes the code a lot easier to understand, test and maintain.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;High cohesion:&lt;/strong&gt; The module have a clear purpose and all parts are working together to perform a single task. As an example, one module could handle database operations, while another module manages the user interface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low cohesion:&lt;/strong&gt; The module is trying to do multiple tasks at once that are not related to each other, which might lead to confusion and more difficulty maintaining the module.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;An example of cohesion&lt;/h3&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://routeralle.se/img/EPIAVD1Sxm-440.avif 440w, https://routeralle.se/img/EPIAVD1Sxm-880.avif 880w, https://routeralle.se/img/EPIAVD1Sxm-1400.avif 1400w&quot; sizes=&quot;auto&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://routeralle.se/img/EPIAVD1Sxm-440.webp 440w, https://routeralle.se/img/EPIAVD1Sxm-880.webp 880w, https://routeralle.se/img/EPIAVD1Sxm-1400.webp 1400w&quot; sizes=&quot;auto&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://routeralle.se/img/EPIAVD1Sxm-336.svg&quot; alt=&quot;Diagram of the NetworkChecker class: its is_host_reachable method creates a connection via socket.create_connection() to test reachability of google.com on port 80&quot; width=&quot;336&quot; height=&quot;285&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; socket

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NetworkChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;is_host_reachable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_connection&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;


checker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NetworkChecker&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;checker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_host_reachable&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The sample code above is an example of how high cohesion could look like. The reason why the class &lt;em&gt;NetworkChecker&lt;/em&gt; is cohesive is due to it having &lt;strong&gt;single responsibility&lt;/strong&gt;; the class focuses on checking network reachability only, and also being &lt;strong&gt;concise&lt;/strong&gt;; it includes only the necessary logic for the specific purpose.&lt;/p&gt;
&lt;p&gt;Before moving on to coupling, I would like to give you an idea of what low cohesion could look like. Below I have added some new rows to the previous snippet.&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; socket
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; time

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NetworkChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;is_host_reachable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_connection&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;log_host_status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;host_status.log&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;reachable&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_host_reachable&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;unreachable&quot;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;a&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; log&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;write&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strftime&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;%Y-%m-%d %H:%M:%S&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; - &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#92;n&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count_words&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; file_path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file_path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;r&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;read&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;split&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; FileNotFoundError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;


checker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NetworkChecker&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;checker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_host_reachable&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
checker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;log_host_status&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;checker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count_words&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;host_status.log&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the sample above, you can see that there are now two new functions in the &lt;em&gt;NetworkChecker&lt;/em&gt; class; &lt;em&gt;log_host_status&lt;/em&gt; and &lt;em&gt;count_words&lt;/em&gt;. This brings a lot of &lt;strong&gt;confusion&lt;/strong&gt; and &lt;strong&gt;difficulty&lt;/strong&gt; in maintaining code, since there is no real relation in neither functionality, clarity or requirements for testing (i.e. testing &lt;em&gt;is_host_reachable&lt;/em&gt; requires mocking sockets, while testing &lt;em&gt;count_words&lt;/em&gt; involves file I/O).&lt;/p&gt;
&lt;h2&gt;Coupling&lt;/h2&gt;
&lt;p&gt;Coupling is all about the dependency between different modules. The goal is to have as loose coupling as possible to make a system or application more flexible and easier to modify.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Loose coupling:&lt;/strong&gt; The modules are quite independent from each other and communicate from module to module by utilizing well defined interfaces. This makes it easier to maintain or exchange a module without affecting the rest of the system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tight coupling:&lt;/strong&gt; The modules are strongly dependent on each others internal implementations. This makes it hard to maintain a system, since a change to one module often requires change in other modules.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;An example of coupling&lt;/h3&gt;
&lt;p&gt;Let’s use the same sample code that we had for cohesion but rewrite it to being loosely coupled. I will do this by implementing some abstraction.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://routeralle.se/img/WeyH_eQ03B-440.avif 440w, https://routeralle.se/img/WeyH_eQ03B-880.avif 880w, https://routeralle.se/img/WeyH_eQ03B-1400.avif 1400w&quot; sizes=&quot;auto&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://routeralle.se/img/WeyH_eQ03B-440.webp 440w, https://routeralle.se/img/WeyH_eQ03B-880.webp 880w, https://routeralle.se/img/WeyH_eQ03B-1400.webp 1400w&quot; sizes=&quot;auto&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://routeralle.se/img/WeyH_eQ03B-760.svg&quot; alt=&quot;Diagram of the abstract base class HostReachabilityChecker, its concrete implementation NetworkChecker, and the display_host_status function that invokes the reachability check through the abstraction&quot; width=&quot;760&quot; height=&quot;397&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; socket
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; abc &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; ABC&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; abstractmethod

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HostReachabilityChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ABC&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    an abstract base class defining the interface for reachability checkers
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@abstractmethod&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;is_host_reachable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NetworkChecker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HostReachabilityChecker&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    concrete implementation of HostReachabilityChecker using sockets
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;is_host_reachable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;create_connection&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timeout&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;timeout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;display_host_status&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;checker&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;
    function to display the reachability of a host
    &quot;&quot;&quot;&lt;/span&gt;
    status &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;reachable&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; checker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;is_host_reachable&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;unreachable&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&quot;host &#39;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;hostname&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; is &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;status&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; on port &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


checker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NetworkChecker&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
display_host_status&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;checker&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the code above, we now have an abstract base class called &lt;code&gt;HostReachabilityChecker&lt;/code&gt;. This is to define a common interface for checking host reachability. The abstraction allows us to decouple the &lt;code&gt;display_host_status&lt;/code&gt; function from &lt;code&gt;NetworkChecker&lt;/code&gt;. By relying on the interface rather than the implementation, &lt;code&gt;display_host_status&lt;/code&gt; becomes more flexible and reusable (fulfilling the modular purpose).&lt;/p&gt;
&lt;p&gt;If we want to change the way host reachability is checked, for example, the way host reachability is checked using some other protocol or method, then we can do this by creating a new class implementing &lt;em&gt;HostReachabilityChecker&lt;/em&gt; without touching the existing code. In general, such separation is also good regarding testability since it is easy to mock an interface.&lt;/p&gt;
&lt;h2&gt;Connection between cohesion and coupling&lt;/h2&gt;
&lt;p&gt;A well-designed system seeks high cohesion and loose coupling. High cohesion ensures each module focuses on a single, well-defined task, whereas loose coupling will enable a module to work with others without tight coupling. Together, these principles create a codebase that is easier to maintain, extend, and adapt, fostering flexibility, scalability, and long-term reliability.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Understanding the IEEE Standard 828-2012</title>
    <link href="https://routeralle.se/2025/understanding-the-ieee-standard-828-2012/" />
    <updated>2025-03-05T00:00:00Z</updated>
    <id>https://routeralle.se/2025/understanding-the-ieee-standard-828-2012/</id>
    <content type="html">&lt;p&gt;Tonight I had a refreshment on SCM (Software Configuration Management) by reading the IEEE Std 828-2012. Software development often involves multiple contributors, complex systems, and rapidly changing requirements. In such an environment, keeping track of changes and ensuring that software artifacts remain consistent and reliable is paramount. This is where that standard comes in, to outline some best practices for SCM. The following sections will cover a shorter summary of the standard.&lt;/p&gt;
&lt;h2&gt;What is the IEEE Standard 828-2012?&lt;/h2&gt;
&lt;p&gt;The standard which is formally titled “IEEE Standard for Configuration Management in System and Software Engineering” defines the minimum requirements for creating and sustaining an effective SCM plan. It focuses on ensuring that all software-related articats (source code, documentation, design specifications, tests, etc.) are properly controlled, monitored, and traceable throughout the SDLC (Software Development Lifecycle).&lt;/p&gt;
&lt;p&gt;The key outcome is to help teams maintain clarity over changes and mitigate risks such as version conflicts or loss of important data.&lt;/p&gt;
&lt;h2&gt;Key components&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;SCM planning&lt;/strong&gt;&lt;br&gt;
The standard requires a written and clearly defined SCMP (Software Configuration Management Plan). The SCMP establishes the scope, responsibilities, and tools utilized for the project SCM activities. It should specify how the software configurations are determined, track changes, who is authorized to make changes, and how records are maintained.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration identification&lt;/strong&gt;&lt;br&gt;
This aspect deals with systematic labeling and organizing all software artifacts so they can be easily referenced and retrieved. Configuration identification involves:
&lt;ul&gt;
&lt;li&gt;defining naming conventions&lt;/li&gt;
&lt;li&gt;versioning protocols&lt;/li&gt;
&lt;li&gt;establishing a baseline (snapshot at a specific point in time)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration control&lt;/strong&gt;&lt;br&gt;
This ensures that only authorized and reviewed changes are incorporated into the baseline. This often involves:
&lt;ul&gt;
&lt;li&gt;change requests and approvals to prevent unauthorized changes&lt;/li&gt;
&lt;li&gt;a formal process for evaluating, testing, and documenting every change&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration status accounting&lt;/strong&gt;&lt;br&gt;
This process tracks and reports on the status of all changes and configuration items (CIs). Through status accounting:
&lt;ul&gt;
&lt;li&gt;teams know &lt;em&gt;who&lt;/em&gt; changed &lt;em&gt;what&lt;/em&gt;, &lt;em&gt;when&lt;/em&gt;, and &lt;em&gt;why&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;current versions of all artifacts are known at any point&lt;/li&gt;
&lt;li&gt;historical data is preserved for auditing and troubleshooting&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration audits&lt;/strong&gt;&lt;br&gt;
Audits ensure that the software and its documentation match the established configuration records. The primary audits are functional and physical.
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Functional audits&lt;/strong&gt;: Confirm that functionality meets the requirements&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Physical audits&lt;/strong&gt;: Check that the documented components match the actual system components in use&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Release management and delivery&lt;/strong&gt;&lt;br&gt;
This step ensures that built software, documentation, and other deliverables are packaged, labeled, and handed off securely. Proper release management involves things such as:
&lt;ul&gt;
&lt;li&gt;maintaining a record of what has been released&lt;/li&gt;
&lt;li&gt;ensuring the reproducibility of releases (the ability to do a rebuild or rollback if needed)&lt;/li&gt;
&lt;li&gt;distributing releases with clarity around versioning and compatibility information&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Why the standard matters&lt;/h2&gt;
&lt;p&gt;IEEE 828-2012 is important because it helps teams keep software changes in order and in a neat way. Without proper configuration management, software projects might be catastrophic, leading to faults, lost work, and confusion. It is valuable because of the following points&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Better collaboration&lt;/strong&gt;: It provides a structured process which allows multiple team members to work on the same project without conflicts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fewer mistakes&lt;/strong&gt;: With proper version control and approval processes, changes are reviewed before being implemented, reducing errors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy tracking&lt;/strong&gt;: Every change is recorded, making it easier to trace issues and understand how the software evolved over time&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Regulatory compliance&lt;/strong&gt;: Many industries require strict documentation and change tracking. IEEE 828-2012 helps meet these requirements&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplifies maintenance&lt;/strong&gt;: When software needs updates or bug fixes, clear records help teams make changes without breaking existing features&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By following this standard, organizations can create more reliable software, improve efficiency, and reduce risks in the development process.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Cisco DEVCOR 350-901 passed</title>
    <link href="https://routeralle.se/2025/cisco-devcor-350-901-passed/" />
    <updated>2025-03-08T00:00:00Z</updated>
    <id>https://routeralle.se/2025/cisco-devcor-350-901-passed/</id>
    <content type="html">&lt;p&gt;Yesterday I passed the Cisco DEVCOR 350-901 exam and fulfilled the DevNet Professional certification. To accompany that I today have the Credly badges to prove it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.credly.com/badges/2de85745-4763-4fdd-b149-8c485db51bce&quot;&gt;Cisco Certified Network Professional Automation (CCNP Automation)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.credly.com/badges/127fc48b-2ebd-43d5-b7a3-dcb35cb9a7b7&quot;&gt;Cisco Certified Specialist – Automation Core&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This was my first try on the exam and I must say I enjoyed it a lot, both the actual exam and the study journey. It was a really fun exam to study for and I believe it covered a lot of great topics for the modern network engineer.&lt;/p&gt;
&lt;h2&gt;Study resources used&lt;/h2&gt;
&lt;p&gt;My main study resource for the Cisco DEVCOR exam was the OCG (&lt;em&gt;ISBN: 9780137370443&lt;/em&gt;). This book provided a structured approach to understanding key concepts and exam topics, as well as other perspectives to the world of software engineering and infrastructure automation.&lt;/p&gt;
&lt;p&gt;In addition to the OCG, I extensively used Ciscos platform API documentation to dive deeper into automation and programmability of the different offerings. The official documentation was great for understanding how different APIs work and how to implement them effectively.&lt;/p&gt;
&lt;p&gt;To gain hands-on experience, I leveraged the Cisco DevNet Sandbox labs. Following the exam blueprint, I practiced real-world scenarios in a lab environment, reinforcing my knowledge and improving my troubleshooting skills.&lt;/p&gt;
&lt;p&gt;However, as learning never ends. I will end this post with a fun code-influenced line.&lt;/p&gt;
&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; exam_status &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pass&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    continue_learning&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>Why post-quantum encryption matters</title>
    <link href="https://routeralle.se/2025/why-post-quantum-encryption-matters/" />
    <updated>2025-06-18T00:00:00Z</updated>
    <id>https://routeralle.se/2025/why-post-quantum-encryption-matters/</id>
    <content type="html">&lt;p&gt;In the world of cybersecurity, timing is indeed everything. While quantum computers capable of breaking todays encryption schemes may still be years away, the threat they pose is already here. That’s because data does not vanish after it has been transmitted, it is often stored for years. Nation-states and threat actors are already collecting encrypted traffic with the intent to decrypt it once quantum technology catches up. This strategy is known as “harvest now, decrypt later”, which turns todays secure communications into an open book tomorrow.&lt;/p&gt;
&lt;p&gt;This looming vulnerability puts sensitive information at long-term risk. That is why the transition to post-quantum encryption is not about a theoretical exercise for the future. It is an urgent and proactive measure that needs to begin now in order to safeguard the confidentiality of data across modern networks.&lt;/p&gt;
&lt;p&gt;Quantum computing threatens current cryptography like RSA, diffie-hellman (DH) and elliptic-curve diffie-hellman (ECDH) since these encryption schemes rely on math problems – such as factoring large numbers or solving discrete logarithms. These problems take exponential time to crack for a traditional computer, but with quantum computers using qubits instead or regular bits, they can try many possible answers at once. With Shor’s algorithm, quantum computers can quickly spot patterns in numbers – which in theory makes it possible to crack these encryptions in hours or potentially minutes. This is why we need to convert to quantum-safe encryption, which is already today supported in some network operating systems, as in Cisco IOS-XE. Let’s dive in to how we can accomplish this when setting up a VPN connection.&lt;/p&gt;
&lt;h2&gt;Cisco IOS-XE&lt;/h2&gt;
&lt;p&gt;To harden IKEv2/IPsec VPNs against future quantum threats, Cisco IOS-XE supports RFC 8784, allowing the integration of post-quantum preshared keys (also known as PPK). This setup enhances security by mixing a quantum-safe PPK into the IKEv2 key derivation process. See the example below.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://routeralle.se/img/QIje4vjO5L-440.avif 440w, https://routeralle.se/img/QIje4vjO5L-624.avif 624w&quot; sizes=&quot;auto&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://routeralle.se/img/QIje4vjO5L-440.webp 440w, https://routeralle.se/img/QIje4vjO5L-624.webp 624w&quot; sizes=&quot;auto&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://routeralle.se/img/QIje4vjO5L-440.png&quot; alt=&quot;Diagram comparing IKEv2 key derivation without and with a PPK: mixing a Postquantum Preshared Key into the key derivation function yields a session key that is safe from quantum attacks&quot; width=&quot;624&quot; height=&quot;325&quot; srcset=&quot;https://routeralle.se/img/QIje4vjO5L-440.png 440w, https://routeralle.se/img/QIje4vjO5L-624.png 624w&quot; sizes=&quot;auto&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;There are two possible ways of generating a PPK:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Manually providing the configuration with the PPKs on responder and initiator&lt;/li&gt;
&lt;li&gt;Using the Cisco Secure Key Integration Protocol (SKIP) for dynamic PPK provisioning with an external key source&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Configuration&lt;/h3&gt;
&lt;p&gt;To summarize this blog post I thought it would be fun to show how we can accomplish this in a lab. The lab will be built on the following topology.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://routeralle.se/img/tVYUzjICyI-440.avif 440w, https://routeralle.se/img/tVYUzjICyI-880.avif 880w&quot; sizes=&quot;auto&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://routeralle.se/img/tVYUzjICyI-440.webp 440w, https://routeralle.se/img/tVYUzjICyI-880.webp 880w&quot; sizes=&quot;auto&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://routeralle.se/img/tVYUzjICyI-440.png&quot; alt=&quot;Lab topology: two Catalyst 8000V routers, R1 and R2, connected over the 172.22.0.0/30 network&quot; width=&quot;880&quot; height=&quot;292&quot; srcset=&quot;https://routeralle.se/img/tVYUzjICyI-440.png 440w, https://routeralle.se/img/tVYUzjICyI-880.png 880w&quot; sizes=&quot;auto&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;On both R1 and R2, let’s define the PPK manually&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;! R1 config
crypto ikev2 keyring PPK-KEYRING
 peer 1
  address 172.22.0.2 255.255.255.255
  ppk manual id ppk_id key ROUTERALLE

! R2 config
crypto ikev2 keyring PPK-KEYRING
 peer 1
  address 172.22.0.1 255.255.255.255
  ppk manual id ppk_id key ROUTERALLE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After this, we can normally use the keyring in our profile.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;! R1 config
crypto ikev2 profile IKEv2-PROF
 match identity remote address 172.22.0.2 255.255.255.255
 authentication remote pre-shared key ROUTERALLE
 authentication local pre-shared key ROUTERALLE
 keyring ppk PPK-KEYRING

! R2 config
crypto ikev2 profile IKEv2-PROF
 match identity remote address 172.22.0.1 255.255.255.255
 authentication remote pre-shared key ROUTERALLE
 authentication local pre-shared key ROUTERALLE
 keyring ppk PPK-KEYRING
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don’t forget about a transform-set before making the IPsec profile.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;crypto ipsec transform-set TS-AES256 esp-gcm 256
 mode tunnel
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then bind this information to an IPsec profile&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;crypto ipsec profile IPSEC-PPK-PROF
 set transform-set TS-AES256
 set ikev2-profile IKEv2-PROF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can arrange the tunnel interface in our two routers.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;! R1 config
interface Tunnel10
 ip address 10.1.1.1 255.255.255.252
 tunnel source GigabitEthernet1
 tunnel destination 172.22.0.2
 tunnel protection ipsec profile IPSEC-PPK-PROF

! R2 config
interface Tunnel10
 ip address 10.1.1.2 255.255.255.252
 tunnel source GigabitEthernet1
 tunnel destination 172.22.0.1
 tunnel protection ipsec profile IPSEC-PPK-PROF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s verify the state of our tunnel on one of the routers by issuing a show command for viewing the security association.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;R2#show crypto ikev2 sa detailed 
 IPv4 Crypto IKEv2  SA 

Tunnel-id Local                 Remote                fvrf/ivrf            Status 
1         172.22.0.2/500        172.22.0.1/500        none/none            READY  
      Encr: AES-CBC, keysize: 256, PRF: SHA512, Hash: SHA512, DH Grp:19, Auth sign: PSK, Auth verify: PSK, QR
&amp;lt;-- omitted output --&amp;gt;
      Status Description: Negotiation done
      Local id: 172.22.0.2
      Remote id: 172.22.0.1
&amp;lt;-- omitted output --&amp;gt;
      Initiator of SA : Yes
      Quantum-safe Encryption using Manual PPK
      PEER TYPE: IOS-XE
&amp;lt;-- omitted output --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can now see that the encryption used is quantum-safe by the line “Quantum-safe Encryption using Manual PPK”.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Choosing the right package manager for node applications</title>
    <link href="https://routeralle.se/2026/choosing-the-right-package-manager-for-node-applications/" />
    <updated>2026-05-26T00:00:00Z</updated>
    <id>https://routeralle.se/2026/choosing-the-right-package-manager-for-node-applications/</id>
    <content type="html">&lt;p&gt;Like many people who work with node applications, the package manager journey is shaped by whatever solved the biggest pain at the time.&lt;/p&gt;
&lt;p&gt;I started with npm, because, that’s where everyone starts.&lt;/p&gt;
&lt;p&gt;After npm I moved to Yarn during the period where npm installs felt slow and unreliable, especially when working on larger projects and React Native environments. Yarn brought faster installs, lockfile consistency, and generally felt more stable for day-to-day work.&lt;/p&gt;
&lt;p&gt;At the time, it genuinely improved the developer experience.&lt;/p&gt;
&lt;p&gt;But over the last few years, npm improved a lot, and the ecosystem changed again. That’s when I discovered pnpm. What immediately stood out with pnpm was how much more efficient it feels.&lt;/p&gt;
&lt;p&gt;Instead of copying the same dependencies into every project, pnpm uses a content addressable store and links packages into projects, which in practice means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;less disk usage&lt;/li&gt;
&lt;li&gt;faster installs across multiple projects&lt;/li&gt;
&lt;li&gt;cleaner dependency management&lt;/li&gt;
&lt;li&gt;and better enforcement of dependency correctness&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last point is surprisingly important.&lt;/p&gt;
&lt;p&gt;The pnpm package manager exposes dependency issues that npm and Yarn sometimes let slide. Packages that rely on undeclared transitive dependencies tend to break faster under pnpm, which at first sounds annoying, but in my experience have resulted in healthier projects.&lt;/p&gt;
&lt;p&gt;For my node applications and automation tooling, pnpm has become the default.&lt;/p&gt;
&lt;p&gt;I still use npm when needed, and Yarn still makes sense in some ecosystems, like older React Native setups. But if I am starting a new node project today, pnpm is usually where I begin. Not because npm or Yarn are bad, but because pnpm just feels like the package manager most aligned with how modern JavaScript projects should work.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The network became code</title>
    <link href="https://routeralle.se/2026/the-network-became-code/" />
    <updated>2026-06-16T00:00:00Z</updated>
    <id>https://routeralle.se/2026/the-network-became-code/</id>
    <content type="html">&lt;p&gt;There used to be a person who knew the network, who was an artisan and for a long time the work around networks genuinely demanded artisanship. A network was a physical thing assembled for physical boxes, each configured through its own command line dialect, each subtly different from its neighbor. Expertise meant memorizing those dialects and developing an intuition for where the bodies were buried. It was skilled, valuable work. It was also completely unable to keep up with what came next.&lt;/p&gt;
&lt;p&gt;The pressure on the previous model made it untenable. We could not scale tens of thousands of devices (physical or virtual constructs) by manually touching each and every one of them throughout their lifecycle, and the moment a “device” might live for ninety seconds before vanishing, the console cable becomes a relic. You cannot log in to something that no longer exists. The cloud finished the job when it redefined what a network even is, not a rack you can point at, but a set of abstractions you summon with an API call. And the applications riding on top stopped shipping in quarterly events and started shipping several times before lunch, leaving no room for a human to approve every change in the path. Scale, ephemerality, and pace all pushed in the same direction, and the artisan’s model had nowhere left to stand.&lt;/p&gt;
&lt;p&gt;So the work changed in one decisive way, we stopped telling the network what to do and started telling it what to be. The artisan issued commands, just a sequence of instructions typed into a box. The modern approach declares a desired state, these networks should exist, this traffic is allowed, these routes are advertised, and a system works out how to make reality match. It sounds like a small semantic shift. It is the whole revolution. Because a description of desired state is just text, and text goes in a file, and a file goes in version control alongside the application code, and at that exact moment the network inherits everything software engineering spent decades learning.&lt;/p&gt;
&lt;p&gt;It inherits history, where every change is recorded, attributed, and revertible. It inherits review, a second engineer reading a change before it touches anything real. It inherits testing and continuous integration that can validate a configuration, even stand up a virtual replica of the topology, before a single packet is affected. It inherits pipelines that apply changes automatically and roll them back when the signals look wrong. The 2 am fix stops being an act of heroic memory and becomes a pull request. The network is no longer a fragile thing one person understands, it is a body of code a team can reason about together.&lt;/p&gt;
&lt;p&gt;This is where network design and software design quietly became the same discipline. A modern system holds two pictures at once, the desired state you declared and the observed state that is actually true, and runs a controller whose only job is to notice the gap and close it, continuously, without being asked. That reconciliation loop is the engine inside Kubernetes, working a cluster toward its manifests. It is the engine inside the tools that provision cloud infrastructure from declarative definitions. And it is exactly how software defined networking works, a controller programming the fabric to match intent and healing around failures as they appear. Three different layers, one identical shape. The engineer who understands the pattern in one understands it in all of them, and that transfer, not any single tool, is the real story of the modern era.&lt;/p&gt;
&lt;p&gt;The line between “the network” and “the application” is dissolving as a result. Service meshes lift routing and traffic policy up into software that travels with the code. APIs have replaced the console cable, so an application can reshape its own connectivity at runtime as casually as it allocates memory. There is no longer a network team throwing configs over a wall to an applications team; there is one system, expressed in code, observed through shared telemetry, operated by people fluent across the layers.&lt;/p&gt;
&lt;p&gt;None of which makes the old knowledge worthless, you cannot simply automate what you do not understand, and a clean abstraction over a system you cannot reason about is only a faster way to cause an outage. But that knowledge now lives in code and in systems thinking rather than in muscle memory and a console session. The destination is a network that disappears, not because it stopped mattering, but because it finally became programmable and self-healing enough to recede into the background, the way all good infrastructure eventually should. We spent decades unable to look away from the network. We are finally building the kind we can trust to look after itself.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Taking on a new programming language</title>
    <link href="https://routeralle.se/2026/taking-on-a-new-programming-language/" />
    <updated>2026-08-06T00:00:00Z</updated>
    <id>https://routeralle.se/2026/taking-on-a-new-programming-language/</id>
    <content type="html">&lt;p&gt;Learning a new programming language is rarely just about learning new syntax.&lt;/p&gt;
&lt;p&gt;That came clear to me when I recently had to work on a project written in Prel. I came into it with most of my experience in Python, where I was comfortable with the language, its conventions and also the way problems are typically structured. Perl was quite unfamiliar territory, I have seen some code in the past but never really embraced and worked with it. So the biggest challenge was not simply that the language looked different.&lt;/p&gt;
&lt;p&gt;I inherited a quite difficult and legacy codebase and at first sight, my instinct was to approach the project the same way I would approach a new Python task: identify the part that needs to be changed, understand the immediate inputs and outputs and then start improving the implementation. That approach works well when the system is familiar and the code follows conventions you already understand.&lt;/p&gt;
&lt;p&gt;In this case, it was totally the wrong starting point.&lt;/p&gt;
&lt;h2&gt;The discomfort of unfamiliar code&lt;/h2&gt;
&lt;p&gt;Perl has a reputation for being expressive, flexible and sometimes difficult to read. In a legacy system, all three qualities can appear at once.&lt;/p&gt;
&lt;p&gt;The code contained some unfamiliar syntax, implicit behavior, compact expressions, global state and assumptions that were not documented anywhere. Variables seemed to change meaning depending on where they were used. Subroutines had side effects that were not obvious from their names. Some parts looked unnecessarily complicated, while others appeared simple but were connected to behavior elsewhere in the application.&lt;/p&gt;
&lt;p&gt;My initial reaction was to translate everything mentally to a language that I am comfortable with, like Python.&lt;/p&gt;
&lt;p&gt;I kept asking myself how I would write the same logic using dictionaries, functions, classes, exceptions or some clearer control flow. That helped me understand individual lines but it also created a dangerous bias. I started judging the Perl code according to Pythonic ways of working before I fully understood why it had been written that way.&lt;/p&gt;
&lt;p&gt;Different languages encourage different styles. More importantly, old systems develop their own internal logic over time. A piece of code may look strange because it is poorly written but it may also look strange because it protects against a production issue that occurred years ago.&lt;/p&gt;
&lt;p&gt;Without context, the two situations can become difficult to distinguish from one another.&lt;/p&gt;
&lt;h2&gt;Reading before changing&lt;/h2&gt;
&lt;p&gt;I believe that the most important lesson from the project was very simple. Read the code before trying to change the code. It can sound very obvious but in practice it requires discipline.&lt;/p&gt;
&lt;p&gt;Reading the code is not the same as scanning until you find the line you want to edit. It means tracing the data through the system, identifying where the values originate, understanding which subroutines that mutate state, and also looking for dependencies that are not visible from the immediate call path.&lt;/p&gt;
&lt;p&gt;I had to slow down in my work. Instead of immediately rewriting unfamiliar sections, I started documenting what I could prove about the system. I followed variables from input to output. I searched every place a subroutine was called. I compared similar code paths. I inspected logs and existing tests. Where tests did not exist, I created small experiments to verify how the code behaved.&lt;/p&gt;
&lt;p&gt;The goal was not to understand all of Perl. It was to understand this particular system well enough to make a safe change. That shift made a significant difference.&lt;/p&gt;
&lt;p&gt;Once I stopped treating the codebase as something that needed to be cleaned up immediately, I began to see its structure. Patterns started emerging. Some confusing decisions were still questionable however, but others turned out to be deliberate. Code that initially looked redundant was handling edge cases. Values that appeared unused were consumed indirectly. Certain conventions were inconsistent by modern standards but consistent within the application itself.&lt;/p&gt;
&lt;p&gt;The code became less mysterious once I learned to observe it on its own terms.&lt;/p&gt;
&lt;h2&gt;Legacy code might be a communication problem&lt;/h2&gt;
&lt;p&gt;Working on this project reminded me that working with legacy code is not only a technical problem. It is a communication problem across time.&lt;/p&gt;
&lt;p&gt;The original developers made decisions based on requirements, constraints, incidents and some deadlines that I could no longer see. The code was their remaining explanation, even though it was incomplete and missing documentation. My job was to reconstruct enough of that missing context to change the system in a responsible manner.&lt;/p&gt;
&lt;p&gt;It is easy to enter an unfamiliar codebase and immediately notice everything I myself would do differently. It is much hared to recognize that our preferred solutions is shaped by our own experience, tools and assumptions.&lt;/p&gt;
&lt;p&gt;Modernizing code can be valuable. Refactoring can reduce risk and make future work on the project easier. But changing code before understanding its behavior can turn an ugly but functioning system into a clean looking failure.&lt;/p&gt;
&lt;p&gt;I believe that a few questions that will follow along to the next legacy project I work with is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What does the code currently do?&lt;/li&gt;
&lt;li&gt;Why might it have been written this way?&lt;/li&gt;
&lt;li&gt;What is the smallest safe change that solves the actual problem?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Only after answering those questions should any writing begin.&lt;/p&gt;
&lt;h2&gt;Growth that happens outside of the comfort zone&lt;/h2&gt;
&lt;p&gt;Most developers have a language in which they feel at home. For me, that language is Python. Its readability, ecosystem and overall development experience align well with how I like to solve my problems. But comfort can also create blind spots.&lt;/p&gt;
&lt;p&gt;Working in Perl forced me to operate without many of my usual instincts. I had to learn new conventions, question familiar assumptions and last but not least, accept that my first interpretation of the code was often incomplete. That discomfort was valuable.&lt;/p&gt;
&lt;p&gt;Learning a new programming language is not only about adding another technology to the CV. It is an opportunity to examine the habits we have developed in our primary language. It shows us which ideas a fundamental and which are simply conventions we have become accustomed to.&lt;/p&gt;
&lt;p&gt;The Perl project did not make me abandon my preference in Python. It made me a better developer in general by strengthening some of my weaknesses. It is hard to change both familiar and unfamiliar code unless you can prove that you understand it.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Goodbye WordPress: rebuilding the blog</title>
    <link href="https://routeralle.se/2026/goodbye-wordpress-rebuilding-routeralle/" />
    <updated>2026-08-10T00:00:00Z</updated>
    <id>https://routeralle.se/2026/goodbye-wordpress-rebuilding-routeralle/</id>
    <content type="html">&lt;p&gt;After several years of running this blog on WordPress, I have now replaced it with a static site built with Eleventy. The two big reasons were hosting costs and to have something that feels more like me.&lt;/p&gt;
&lt;p&gt;If you have visited the site before, you will notice that things look quite different around here. That is very much the point.&lt;/p&gt;
&lt;h2&gt;Why leave WordPress&lt;/h2&gt;
&lt;p&gt;WordPress has served me well and I have nothing bad to say about it as a platform. But for a small blog like this one, it started to feel like driving a truck to the mailbox.&lt;/p&gt;
&lt;p&gt;The site was running on a Lightsail instance in AWS, which meant a virtual machine humming along all day, every day, just to serve a handful of static pages to the sites visitors. That is a few dollars every month for compute that mostly sits idle. On top of that comes the part nobody talks about when they recommend WordPress: the maintenance. Core updates, plugin updates, PHP versions, backups and the constant background noise of bots probing wp-login.php. None of it is difficult, but it is a recurring chore for the site. Now that I want to get into writing more frequently, I would like for my focus to stay on that and not putting effort into the negative sides that WordPress comes with.&lt;/p&gt;
&lt;p&gt;A blog is text. Text does not need a database and an application server. It needs a place to live and a way to get there.&lt;/p&gt;
&lt;h2&gt;Getting my own style&lt;/h2&gt;
&lt;p&gt;The second reason was more personal. With WordPress you pick a theme, and no matter how much you adjust it, the site always ends up looking like, well, a WordPress theme. Mine never really felt like mine.&lt;/p&gt;
&lt;p&gt;This time I designed the site from scratch. It is heavily inspired by the terminal, which felt fitting for a blog that is mostly about networking and automation. Monospace fonts in the navigation, a blinking cursor in the wordmark and headings that look like markdown. There is a light and a dark mode that follows your system preference, with a small toggle if you disagree with your operating system. The whole stylesheet is one hand-written CSS file. No frameworks, no build pipeline for the styling, nothing to update next year. It is a simple design, but it is my simple design.&lt;/p&gt;
&lt;h2&gt;The new stack&lt;/h2&gt;
&lt;p&gt;The site is built with &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;, a static site generator that gets out of the way. Posts are plain markdown files in a git repository. The templates are a handful of Nunjucks files. That is more or less it.&lt;/p&gt;
&lt;p&gt;Hosting is an S3 bucket behind CloudFront, with a certificate from ACM. Deployment happens through GitHub Actions: every push to the main branch builds the site and syncs it to the bucket using OIDC, so there are no long-lived AWS keys stored anywhere. Publishing a post is now as simple as:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; posts/2026-08-10-my-new-post.md
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Add new post&quot;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;About a minute later it is live. Drafts are just a &lt;code&gt;draft: true&lt;/code&gt; line in the frontmatter, visible locally but excluded from the production build.&lt;/p&gt;
&lt;h2&gt;What it costs now&lt;/h2&gt;
&lt;p&gt;The old setup was a Lightsail instance billed every hour of every month. The new one is S3 storage measured in cents, CloudFront traffic that for a site this size stays within very little money, and a certificate that costs nothing. The GitHub Actions minutes are within the free tier. For a personal blog, the hosting bill has essentially gone from a subscription to a rounding error, lol.&lt;/p&gt;
&lt;p&gt;And since the whole site is a git repository, the backup strategy is the same as for any other code I write.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;git push&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
</feed>