<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Architektur on markob.de</title><link>https://markob.de/thema/architektur/</link><description>Recent content in Architektur on markob.de</description><generator>Hugo</generator><language>de-DE</language><lastBuildDate>Mon, 24 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://markob.de/thema/architektur/index.xml" rel="self" type="application/rss+xml"/><item><title>Das Framework ist nur ein Detail. Das Domainmodell ist es nicht.</title><link>https://markob.de/limesurvey/domain-model/</link><pubDate>Mon, 24 Aug 2026 00:00:00 +0000</pubDate><guid>https://markob.de/limesurvey/domain-model/</guid><description>&lt;p&gt;In &lt;a href="https://markob.de/limesurvey/yii3"&gt;Das Framework ist nur ein Detail&lt;/a&gt; war unsere These: Neue Anwendungslogik sollte nicht davon abhängen, ob am äußeren Rand Yii, Slim oder ein anderes Framework HTTP-Requests verarbeitet. Das Framework sollte Adapter sein, nicht Architektur.&lt;/p&gt;
&lt;p&gt;Daran hat sich nichts geändert. Inzwischen beschäftigt uns allerdings eine Frage, die noch eine Ebene tiefer geht: Wenn wir das Framework aus dem Zentrum von LimeSurvey entfernen – welches Domainmodell wollen wir dort eigentlich erhalten? Begriffe wie &lt;code&gt;QuestionGroup&lt;/code&gt;, &lt;code&gt;Question&lt;/code&gt;, &lt;code&gt;SubQuestion&lt;/code&gt; oder &lt;code&gt;QuestionType&lt;/code&gt; sind für LimeSurvey-Entwickler so selbstverständlich, dass man leicht vergisst, sie überhaupt noch infrage zu stellen. Aber sind das notwendige Konzepte eines Survey-Systems – oder historische Architekturentscheidungen, die uns heute nur deshalb wie Domainlogik erscheinen, weil LimeSurvey seit vielen Jahren so funktioniert?&lt;/p&gt;</description></item><item><title>Das Framework ist nur ein Detail</title><link>https://markob.de/limesurvey/yii3/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><guid>https://markob.de/limesurvey/yii3/</guid><description>&lt;p&gt;In einer &lt;a href="https://careers.limesurvey.org/jobs/Careers/38813000007296145/Full-Stack-Developer-m-f-d"&gt;LimeSurvey-Stellenanzeige für einen Full-Stack-Developer&lt;/a&gt; (Stand: 20. August 2026) taucht unter „Tech We Use&amp;quot; das „Yii-3 PHP Framework&amp;quot; auf – bemerkenswert, denn der aktuelle LimeSurvey-Core basiert weiterhin auf Yii 1.1. Ob damit der bestehende Core migriert werden soll, ob Yii3 nur für neue Komponenten gedacht ist oder ob lediglich einzelne Yii3-Pakete gemeint sind, wissen wir nicht. Für das Folgende spielt das auch keine große Rolle.&lt;/p&gt;
&lt;p&gt;Denn bevor LimeSurvey entscheidet, welches Framework Yii 1.1 irgendwann ersetzt, lohnt sich eine andere Frage: Warum sollte diese Entscheidung für den Anwendungscode überhaupt von Bedeutung sein?&lt;/p&gt;</description></item><item><title>Das LimeSurvey Plugin-Event-System – eine kritische Betrachtung</title><link>https://markob.de/limesurvey/plugin-event-kritik/</link><pubDate>Sat, 09 May 2026 00:00:00 +0000</pubDate><guid>https://markob.de/limesurvey/plugin-event-kritik/</guid><description>&lt;p&gt;LimeSurvey verfügt über ein event-basiertes Plugin-System. Plugins abonnieren Events, reagieren darauf, und können Daten zurückgeben. Das Konzept ist solide – und weit verbreitet in modernen Frameworks. Die Implementierung erzählt eine andere Geschichte.&lt;/p&gt;
&lt;h2 id="was-ein-event-system-leisten-soll"&gt;Was ein Event-System leisten soll&lt;/h2&gt;
&lt;p&gt;Ein Event kommuniziert, dass etwas passiert ist oder passieren wird. Der Name beschreibt das Ereignis. Die Parameter sind bekannt und garantiert. Der Empfänger reagiert – er fragt nicht erst nach, ob die Daten überhaupt vorhanden sind.&lt;/p&gt;</description></item><item><title>SurveyIndex + SurveyRuntimeHelper – Anatomie eines God Flow</title><link>https://markob.de/limesurvey/god-flow/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>https://markob.de/limesurvey/god-flow/</guid><description>&lt;p&gt;Wenn zu viel Verantwortung nicht in einer Klasse steckt, sondern in einem Ablauf&lt;/p&gt;
&lt;p&gt;In den letzten Artikeln dieser Serie haben wir zwei bekannte Antipattern betrachtet: &lt;a href="https://markob.de/create-field-map-die-god-function"&gt;&lt;code&gt;createFieldMap()&lt;/code&gt;&lt;/a&gt; als Beispiel einer Funktion, die zu viele Verantwortlichkeiten in sich vereint, und &lt;a href="https://markob.de/limemailer-anatomie-einer-god-class"&gt;&lt;code&gt;LimeMailer&lt;/code&gt;&lt;/a&gt; als Beispiel einer Klasse, die zu viel weiß, zu viel hält und zu viel tut. Beide Diagnosen folgten derselben Logik: Zu viel Verantwortung an einer Stelle.&lt;/p&gt;
&lt;p&gt;Diesmal geht es um etwas anderes. Nicht eine Funktion. Nicht eine Klasse. Sondern einen Ablauf.&lt;/p&gt;</description></item><item><title>createFieldMap() – die God Function</title><link>https://markob.de/limesurvey/create-field-map-die-god-function/</link><pubDate>Sun, 26 Apr 2026 00:00:00 +0000</pubDate><guid>https://markob.de/limesurvey/create-field-map-die-god-function/</guid><description>&lt;p&gt;&lt;a href="https://markob.de/limesurvey/helper-funktionen"&gt;Im Artikel über die Helper-Funktionen&lt;/a&gt; haben wir &lt;code&gt;common_helper.php&lt;/code&gt; als Ganzes betrachtet – 130+ globale Funktionen, über 11.000 Aufrufe im Code, ein Relikt aus der prozeduralen Ära. &lt;a href="https://markob.de/limemailer-anatomie-einer-god-class"&gt;In einem anderen Artikel&lt;/a&gt; haben wir &lt;code&gt;LimeMailer&lt;/code&gt; als GodClass analysiert: eine Klasse die zu viel weiß, zu viel tut, und deshalb praktisch nicht testbar ist.&lt;/p&gt;
&lt;p&gt;Heute schauen wir auf etwas das noch subtiler ist: eine &lt;strong&gt;GodFunction&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Keine Klasse. Eine einzelne Funktion. Mit über 600 Zeilen Code.&lt;/p&gt;</description></item><item><title>LimeSurvey und die Helper-Funktionen</title><link>https://markob.de/limesurvey/helper-funktionen/</link><pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate><guid>https://markob.de/limesurvey/helper-funktionen/</guid><description>&lt;p&gt;Wer LimeSurvey als Plugin-Entwickler nutzt oder in der Codebasis arbeitet, begegnet früher oder später diesem Muster:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Yii&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;loadHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;common&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Yii&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;loadHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;surveytranslator&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Yii&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;loadHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;replacements&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dahinter steckt ein einfacher Mechanismus: &lt;code&gt;loadHelper('common')&lt;/code&gt; lädt die Datei &lt;code&gt;application/helpers/common_helper.php&lt;/code&gt; und macht ihre Funktionen im globalen Scope verfügbar. Dasselbe Muster findet sich auch bei &lt;code&gt;loadLibrary()&lt;/code&gt;, das auf &lt;code&gt;application/libraries/&lt;/code&gt; zeigt:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$helper&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Yii&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;application.helpers.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$helper&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;_helper&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadLibrary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$library&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Yii&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;application.libraries.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$library&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Der konzeptuelle Unterschied zwischen Helper und Library ist dabei in der LimeSurvey-Codebasis kaum greifbar – beide Mechanismen lösen dasselbe Problem auf dieselbe Art. Das war in einer Zeit sinnvoll, als PHP noch kein Autoloading kannte und Funktionen manuell eingebunden werden mussten. PHP 5.1 war 2005. Composer erschien 2012.&lt;/p&gt;</description></item><item><title>LimeMailer - Anatomie einer God Class</title><link>https://markob.de/limesurvey/limemailer-anatomie-einer-god-class/</link><pubDate>Sun, 22 Mar 2026 00:00:00 +0000</pubDate><guid>https://markob.de/limesurvey/limemailer-anatomie-einer-god-class/</guid><description>&lt;p&gt;&lt;a href="https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/LimeMailer.php"&gt;LimeMailer&lt;/a&gt; ist die zentrale E-Mail-Komponente von LimeSurvey. Sie erbt von PHPMailer, der weit verbreiteten PHP-Mailer-Bibliothek, und erweitert diese um LimeSurvey-spezifische Logik: Umfrage-Templates, Token-Ersetzungen, Anhänge nach E-Mail-Typ, Plugin-Events und vieles mehr.&lt;/p&gt;
&lt;p&gt;Dieser Artikel betrachtet die Klasse nicht als Fehler ihrer Entwickler. Wer in einem laufenden Open-Source-Projekt unter Zeitdruck Features liefert, trifft Entscheidungen, die im Moment vernünftig sind. Technische Schulden entstehen nicht durch Unwissenheit, sondern durch die Realität von Softwareentwicklung. Was hier analysiert wird, ist das Muster – nicht die Person dahinter.&lt;/p&gt;</description></item><item><title>LimeSurvey - ein System im Übergang</title><link>https://markob.de/limesurvey/ein-system-im-uebergang/</link><pubDate>Sun, 01 Mar 2026 00:00:00 +0000</pubDate><guid>https://markob.de/limesurvey/ein-system-im-uebergang/</guid><description>&lt;h2 id="was-ist-limesurvey"&gt;Was ist LimeSurvey?&lt;/h2&gt;
&lt;p&gt;LimeSurvey gehört seit vielen Jahren zu den meistverbreiteten Open-Source-Umfragelösungen im PHP-Ökosystem. Die Plattform ermöglicht die Erstellung, Verwaltung und Auswertung von Online-Umfragen und richtet sich sowohl an einzelne Anwender als auch an Organisationen mit komplexen Anforderungen. Mit einer großen aktiven Installationsbasis und kontinuierlicher Weiterentwicklung ist LimeSurvey ein Projekt, das seit langem produktiv eingesetzt wird. Für Umfragen im akademischen oder organisatorischen Kontext gibt es kaum eine vergleichbare Open-Source-Alternative mit diesem Funktionsumfang.&lt;/p&gt;</description></item></channel></rss>