<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ports and adapters Archives - argumentum GmbH</title>
	<atom:link href="https://argumentum.de/tag/ports-and-adapters/feed/" rel="self" type="application/rss+xml" />
	<link>https://argumentum.de/tag/ports-and-adapters/</link>
	<description>Experten für Softwareentwicklungsprozesse</description>
	<lastBuildDate>Thu, 19 Jun 2025 14:51:24 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://argumentum.de/wp-content/uploads/2023/12/cropped-small_logo-32x32.png</url>
	<title>ports and adapters Archives - argumentum GmbH</title>
	<link>https://argumentum.de/tag/ports-and-adapters/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Ports und Adapters in fünf Minuten</title>
		<link>https://argumentum.de/2025/05/ports-und-adapters-in-fuenf-minuten/</link>
		
		<dc:creator><![CDATA[Hendrik Wagner]]></dc:creator>
		<pubDate>Thu, 22 May 2025 20:16:21 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[hexagonale architektur]]></category>
		<category><![CDATA[onion-architektur]]></category>
		<category><![CDATA[ports and adapters]]></category>
		<guid isPermaLink="false">https://argumentum.de/?p=2244</guid>

					<description><![CDATA[In modernen Softwareentwicklungsprojekten wird mit Prinzipien und Architekturmodellen gearbeitet, um Software wartbarer, nachvollziehbarer und erweiterbar zu gestalten. Ein mögliches – und durchaus sinnvolles – Architekturmodell sind die Ports und Adapters, auch als Hexagonale Architektur oder Onion-Architektur bekannt.]]></description>
										<content:encoded><![CDATA[
<p>In modernen Softwareentwicklungsprojekten wird mit Prinzipien und Architekturmodellen gearbeitet, um Software wartbarer, nachvollziehbarer und erweiterbar zu gestalten. Ein mögliches – und durchaus sinnvolles – Architekturmodell sind die Ports und Adapters, auch als <a href="https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)">Hexagonale Architektur</a> oder Onion-Architektur bekannt (auf die Unterschiede gehen wir später kurz ein).</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><strong>Das Konzept</strong></h2>



<p>Mithilfe von Adaptern werden die entstehende Anwendung und Komponenten, mit denen kommuniziert werden, logisch abgetrennt. Der Anwendungskern wird von den Schnittstellen entfernt und ist von diesen nicht abhängig &#8211; dadurch werden sie einfach austauschbar. Fangen wir mit der einfacheren Seite an &#8211; eine Schnittstelle ruft die Anwendung auf. Dies kann zum Beispiel über eine Oberfläche passieren:</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img fetchpriority="high" decoding="async" width="581" height="242" src="https://argumentum.de/wp-content/uploads/2025/05/hexagon2.drawio.png" alt="Ports and Adapters - Kommunikation der Anwendung mit einem User-Interface" class="wp-image-2246" style="width:804px;height:auto" srcset="https://argumentum.de/wp-content/uploads/2025/05/hexagon2.drawio.png 581w, https://argumentum.de/wp-content/uploads/2025/05/hexagon2.drawio-300x125.png 300w" sizes="(max-width: 581px) 100vw, 581px" /><figcaption class="wp-element-caption"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-contrast-2-color">In dieser Grafik wird die Anwendung von einer Webanwendung aus gesteuert. Die Kommunikation zwischen Frontend und Anwendung kann zum Beispiel mittels REST-API erfolgen – dann empfängt der Adapter die Aufrufe und kommuniziert mittels UI-Port die gewünschte Interaktion mit der Anwendung. In der Regel folgt darauf eine Antwort in Richtung der Webanwendung.</mark></figcaption></figure>
</div>


<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p>In der Umsetzung kann man sich dies einfach vorstellen. Nehmen wir hierzu ein Java-Projekt mit Maven, welches eine Chatanwendung umsetzten soll. Angenommen, es gibt ein <strong>chat-core</strong> Modul. In diesem liegt unser Anwendungskern. Ein weiteres <strong>chat-ui</strong> Modul enthält die Webanwendung. Im Kern gibt es die Klasse <strong>UiPort</strong>, welche eine Methode <strong>sendMessage(String message)</strong> implementiert. Diese Methode kann nun vom Web-Adapter, welcher in dem UI-Modul liegt, aufgerufen werden. Damit ist der Adapter von dem Anwendungskern abhängig. Bei dieser Art von Schnittstelle spricht man von einem <em>Primary Component</em> (dt. primäre Komponente).</p>



<p>Sehen wir uns das ganze mal anhand einem Java EE-Beispiel an:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#d4d4d433" stroke="#d4d4d44d" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#d4d4d433" stroke="#d4d4d44d" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#d4d4d433" stroke="#d4d4d44d" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>/* Diese Klasse ist im chat-core Modul */ 
@ApplicationScoped 
public class UiPort { 
  public void sendMessage(String message) { 
    // Aufruf der Kernlogik zum Nachrichtenversand &#8230; 
  } 
}

/* Diese Klasse ist im chat-ui Modul */ 
@ApplicationScoped 
public class WebAdapter { 
  @Inject UiPort uiPort; // zur Laufzeit wird hier eine Instanz des UiPort eingefügt 
  
  public void enterPressed(String textField) { 
    uiPort.sendmessage(textField); 
  } 
}</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">/* Diese Klasse ist im chat-core Modul */</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">@</span><span style="color: #4EC9B0">ApplicationScoped</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">UiPort</span><span style="color: #D4D4D4"> { </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">sendMessage</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">message</span><span style="color: #D4D4D4">) { </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Aufruf der Kernlogik zum Nachrichtenversand ... </span></span>
<span class="line"><span style="color: #D4D4D4">  } </span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">/* Diese Klasse ist im chat-ui Modul */</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">@</span><span style="color: #4EC9B0">ApplicationScoped</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">WebAdapter</span><span style="color: #D4D4D4"> { </span></span>
<span class="line"><span style="color: #D4D4D4">  @</span><span style="color: #4EC9B0">Inject</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">UiPort</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">uiPort</span><span style="color: #D4D4D4">; </span><span style="color: #6A9955">// zur Laufzeit wird hier eine Instanz des UiPort eingefügt </span></span>
<span class="line"><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">enterPressed</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">textField</span><span style="color: #D4D4D4">) { </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">uiPort</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">sendmessage</span><span style="color: #D4D4D4">(textField); </span></span>
<span class="line"><span style="color: #D4D4D4">  } </span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative">Java</span></div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<p>In die andere Richtung wird es etwas spannender. Wir führen ein weiteres Modul <strong>chat-db </strong>ein, welches unsere Chatnachrichten verwalten soll. Würden wir hier wie eben vorgehen, hätte das zur Folge, dass unsere Anwendung von der Datenbank bzw. dessen Adapter abhängig wäre. Gemäß dem <a href="https://en.wikipedia.org/wiki/SOLID">SOLID</a> Prinzip <em>Dependency-Inversion</em> darf die Anwendung aber nicht von einer Komponente abhängig sein, selbst wenn diese die Komponente steuert (<em>Inversion of Control</em>).</p>



<p>Die Lösung: die Anwendung enthält den <strong>PersistencePort</strong>, ein Interface, welches von dem Anwendungskern aufgerufen wird. Dieser enthält die Methode <strong>storeMessage(String message)</strong>. Die Implementierung dieses Interfaces legen wir nun in den Adapter. Diese wird zur Laufzeit bereitgestellt &#8211; die Abhängigkeit besteht nun hier auch vom DB-Modul auf den Anwendungskern, da dort das zu implementierende Interface liegt. Der Adapter kommuniziert direkt mit der externen Schnittstelle, z.B. Hibernate mit MariaDB. In diesem Falle würde der Adapter auch für die Umwandlung der Anwendungsobjekten in Entitäten verantwortlich sein.</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" width="501" height="242" src="https://argumentum.de/wp-content/uploads/2025/05/hexagon.drawio.png" alt="Ports and Adapters - Kommunikation der Anwendung mit einer Datenbank" class="wp-image-2245" style="width:739px;height:auto" srcset="https://argumentum.de/wp-content/uploads/2025/05/hexagon.drawio.png 501w, https://argumentum.de/wp-content/uploads/2025/05/hexagon.drawio-300x145.png 300w" sizes="(max-width: 501px) 100vw, 501px" /><figcaption class="wp-element-caption"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-contrast-2-color">In dieser Grafik kommuniziert die Anwendung mit einer Datenbank. Die Anwendung reicht dem Adapter über den Port die zu persistierenden Daten. Dieser ist für die Umwandlung in Datenbank-Entitäten und die Persistierung zuständig.</mark></figcaption></figure>
</div>


<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Um die Implementierung des Adapters ohne eine Abhängigkeit ausgehend vom Anwendungskern verwenden zu können, muss man auf <em><a href="https://en.wikipedia.org/wiki/Dependency_injection">Dependency-Injection</a></em> oder eine <em><a href="https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)">Factory</a></em> zurückgreifen. Im Java EE-Kontext kann man diese Injection wie folgt umsetzen:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-bottom-disabled cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#d4d4d433" stroke="#d4d4d44d" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#d4d4d433" stroke="#d4d4d44d" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#d4d4d433" stroke="#d4d4d44d" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><textarea class="code-block-pro-copy-button-textarea" aria-hidden="true" readonly>/* Diese Klasse ist im chat-db Modul */ 
@ApplicationScoped 
public class PersistenceAdapter implements PersistencePort { 
  @Override 
  public void storeMessage(String message) { 
    // Logik für die Persistierung &#8230; 
  } 
} 

/* Dieses Interface ist im chat-core Modul */ 
public interface IPersistencePort { 
  public void storeMessage(String message); 
} 

/* Diese Klasse ist im chat-core Modul */ 
@ApplicationScoped 
public class ChatController { 
  @Inject IPersistencePort persistencePort; // zur Laufzeit wird hier eine Instanz des PersistenceAdapter eingefügt 
  
  // hier kann der Port aufgerufen werden, um Nachrichten zu persistieren 
}</textarea><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">/* Diese Klasse ist im chat-db Modul */</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">@</span><span style="color: #4EC9B0">ApplicationScoped</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">PersistenceAdapter</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">implements</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">PersistencePort</span><span style="color: #D4D4D4"> { </span></span>
<span class="line"><span style="color: #D4D4D4">  @</span><span style="color: #4EC9B0">Override</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">storeMessage</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">message</span><span style="color: #D4D4D4">) { </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Logik für die Persistierung ... </span></span>
<span class="line"><span style="color: #D4D4D4">  } </span></span>
<span class="line"><span style="color: #D4D4D4">} </span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">/* Dieses Interface ist im chat-core Modul */</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">interface</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">IPersistencePort</span><span style="color: #D4D4D4"> { </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">storeMessage</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">message</span><span style="color: #D4D4D4">); </span></span>
<span class="line"><span style="color: #D4D4D4">} </span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">/* Diese Klasse ist im chat-core Modul */</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">@</span><span style="color: #4EC9B0">ApplicationScoped</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">ChatController</span><span style="color: #D4D4D4"> { </span></span>
<span class="line"><span style="color: #D4D4D4">  @</span><span style="color: #4EC9B0">Inject</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">IPersistencePort</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">persistencePort</span><span style="color: #D4D4D4">; </span><span style="color: #6A9955">// zur Laufzeit wird hier eine Instanz des PersistenceAdapter eingefügt </span></span>
<span class="line"><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #6A9955">// hier kann der Port aufgerufen werden, um Nachrichten zu persistieren </span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre><span style="display:flex;align-items:flex-end;padding:10px;width:100%;justify-content:flex-end;background-color:#1E1E1E;color:#c7c7c7;font-size:12px;line-height:1;position:relative">Java</span></div>



<div style="height:50px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><strong>Wieso das Ganze?</strong></h2>



<p>Die beschriebene Trennung zwischen Anwendung und Komponenten bringt einige Vorteile mit sich:</p>



<ul class="wp-block-list">
<li>Komponenten außerhalb der Anwendung sind vollständig austauschbar. Welche Datenbank verwendet wird, und wie mit dieser kommuniziert wird, ist für die Anwendung nicht relevant.</li>



<li>Im Falle von Komponenten, die die Anwendung aufrufen (sog. <em>Driving</em> oder <em>Primary Components</em>), können an einem Port mehrere Adapter (und Komponenten) existieren – so kann der UI-Port sowohl über einen Adapter für eine Webanwendung als auch einen Adapter für eine Mobilanwendung angesprochen werden.</li>



<li>Änderungen an Adaptern beeinflussen die Anwendung nicht, und Änderungen an der Anwendung die Adapter nicht. Nur, wenn die Ports angepasst werden, sind beidseitig Änderungen notwendig.</li>



<li>Die Anwendung sowie die einzelnen Adapter sind leichter testbar – Testframeworks können einfach einen Adapter oder die Anwendung simulieren, um jeweils das Gegenstück in einer Testumgebung zu testen</li>
</ul>



<p>Das ist auch schon alles – zumindest in sehr grundlegender Ausführung. Der wahre Umsetzungsaufwand der hexagonalen Architektur entsteht durch das Mapping und dem Erstellen von guten(!) Ports.</p>



<p>Die Adapter benötigen die Daten oft in einem anderen Format, als es von der Anwendung bereitgestellt wird – Objekte müssen für die Datenbank in Entitäten umgewandelt werden, welche in Tabellen persistiert werden können. Eine REST-API arbeitet mit JSON-Objekten, welche zunächst in für die Anwendung verwendbare Objekte umgewandelt werden müssen, und in der Regel ebenfalls eine Umwandlung in die andere Richtung für Antworten der Anwendung.</p>



<p>Geben die Ports den Adaptern zu sehr die Umsetzung vor, kann es wesentlich schneller notwendig sein, diese anzupassen, sobald sich ein Adapter oder die Anwendung verändert. Die Kunst liegt darin, enge Kopplung zu vermeiden, und zukunftsfähige Ports zu entwerfen.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><strong>Die Variante der Onion-Architektur</strong></h2>



<p>Nun sind Dir die Grundlagen der Ports und Adapters bzw. Hexagonalen Architektur bekannt. Zugleich hast Du nun aber auch fast alle Bausteine der <a href="https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/">Onion-Architektur</a> gelernt – diese baut nämlich effektiv auf die hier beschriebene Architektur auf, nur dass sie außerdem noch in den Anwendungskern selbst blickt:</p>



<p>Auch hier wird nur die Regel der nach innen zeigenden Dependencies angewandt: Kern-Komponenten (die Domain – grundlegende Elemente wie ein Kunde oder Artikel) der Anwendung haben keine Abhängigkeiten auf die Domain-Services (Logik mit mehreren Objekten aus der Domain – beispielsweise Bestellungen). Diese wiederum haben keine Abhängigkeiten auf die Services der Anwendung, welche <em>Use Cases</em> umsetzen und mit unseren Ports sprechen können.</p>



<p>Die Verknüpfung von Architekturkonzepten kann weitergesponnen werden, indem weitere Konzepte zugezogen werden. Hierzu eine Leseempfehlung: <a href="https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/">DDD, Hexagonal, Onion, Clean, CQRS, … How I put it all together</a> von Herberto Graça – praktisch ein All-Inclusive Modell.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading"><strong>Schlusswort</strong></h2>



<p>Ports und Adapters und ihre Verwandten präsentieren einen seriösen Ansatz, wie eine Anwendung sauber aufgebaut werden kann. Das Ganze ist jedoch mit Vorsicht zu genießen: mit der Architektur entsteht signifikanter Umsetzungsaufwand, und kommt nur in mittelgroßen bis großen Anwendungen infrage – wobei letztere möglicherweise mehr von einer dem Anwendungsfall angepassten Variante profitieren. Und wenn die Anwendung mit diesem Konzept umgesetzt werden soll, dann bitte richtig. Nehmt Euch die Zeit, sinnvolle Schnittstellen zu entwerfen, denn das ist eine ganz eigene <a href="https://anchor.fm/dominikusherzberg/episodes/Das-Gesprch-Holger-van-den-Boom----Design-als-Mittel-der-Erschlieung-von-Welt-e111nuj">Philosophie</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
