<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Clean Architecture - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Clean Architecture - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 26 Jul 2026 09:02:31 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/clean-architecture/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ The Observer Design Pattern Handbook: Event-Driven Architecture & Domain-Driven Design in Dart ]]>
                </title>
                <description>
                    <![CDATA[ Every application, at some point, has to deal with a fundamental challenge: something happens, and several other things need to react to it. A user logs in, and the app needs to save a token, cache th ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-observer-design-pattern-handbook-event-driven-architecture-domain-driven-design-in-dart/</link>
                <guid isPermaLink="false">6a59593c2c971321745e7720</guid>
                
                    <category>
                        <![CDATA[ #Domain-Driven-Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Dart ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mobile Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Flutter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Observer Pattern ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ behavioural patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Riverpod ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Clean Architecture ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwaseyi Fatunmole ]]>
                </dc:creator>
                <pubDate>Thu, 16 Jul 2026 22:20:44 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/0621293d-e82e-4f24-bb6e-40dec481c7cd.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Every application, at some point, has to deal with a fundamental challenge: something happens, and several other things need to react to it.</p>
<p>A user logs in, and the app needs to save a token, cache the user profile, fire an analytics event, and navigate to the home screen.</p>
<p>A payment is confirmed, and the inventory needs to update, the user needs a receipt, and the fulfillment system needs to kick off delivery.</p>
<p>A sensor reading changes, and three different UI panels need to reflect the new value simultaneously.</p>
<p>The naïve solution is to write all of that logic in one place. One function that does everything or one class that knows about everything.</p>
<p>This works at first. Then requirements change. A new reaction needs to be added. An existing one needs to be removed. A side effect starts failing and takes everything else down with it. The code becomes a wall of responsibilities that's impossible to test, painful to extend, and dangerous to touch.</p>
<p>The Observer Design Pattern exists to solve exactly this problem. It gives you a structured, production-grade way to say: when this event happens, notify everyone who cares, without the event source knowing who those people are.</p>
<p>In this handbook, you'll learn the Observer pattern from first principles. You'll see how it's implemented in Dart, understand how it connects to Event-Driven Architecture, and discover how it integrates cleanly with Domain-Driven Design and Riverpod in a real Flutter application.</p>
<p>By the end, you won't just understand the pattern. You'll know how to use it deliberately in production code.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-what-is-the-observer-design-pattern">What is the Observer Design Pattern?</a></p>
</li>
<li><p><a href="#heading-the-problem-it-solves">The Problem It Solves</a></p>
</li>
<li><p><a href="#heading-core-components">Core Components</a></p>
</li>
<li><p><a href="#heading-implementing-observer-in-dart">Implementing Observer in Dart</a></p>
</li>
<li><p><a href="#heading-a-real-world-example-the-login-flow">A Real-World Example: The Login Flow</a></p>
</li>
<li><p><a href="#heading-making-it-production-grade-with-a-generic-eventbus">Making It Production-Grade with a Generic EventBus</a></p>
</li>
<li><p><a href="#heading-observer-is-already-in-your-flutter-code">Observer Is Already in Your Flutter Code</a></p>
</li>
<li><p><a href="#heading-deep-dive-into-event-driven-architecture">Deep Dive Into Event-Driven Architecture</a></p>
</li>
<li><p><a href="#heading-application-in-domain-driven-design">Application in Domain-Driven Design</a></p>
</li>
<li><p><a href="#heading-the-riverpod-hybrid-clean-architecture-in-practice">The Riverpod Hybrid: Clean Architecture in Practice</a></p>
</li>
<li><p><a href="#heading-testing-the-observer-architecture">Testing the Observer Architecture</a></p>
</li>
<li><p><a href="#heading-when-to-use-the-observer-pattern">When to Use the Observer Pattern</a></p>
</li>
<li><p><a href="#heading-when-not-to-use-it">When Not to Use It</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-the-observer-design-pattern">What is the Observer Design Pattern?</h2>
<p>The Observer pattern is a behavioural design pattern that defines a one-to-many dependency between objects. When one object changes state or fires an event, all of its dependents are notified and updated automatically.</p>
<p>Think of a newspaper subscription service. The newspaper publisher doesn't know who its individual subscribers are. It doesn't call each reader personally. It publishes the paper, and every subscriber who signed up receives it.</p>
<p>A subscriber can cancel at any time. A new subscriber can join at any time. The publisher's job never changes. It just publishes.</p>
<p>That's the Observer pattern in plain terms.</p>
<p>The publisher is called the <strong>Subject</strong>. The subscribers are called <strong>Observers</strong>. The newspaper is the <strong>event</strong>.</p>
<p>The pattern was formally defined in the Gang of Four book, Design Patterns: Elements of Reusable Object-Oriented Software. It remains one of the most widely used patterns in software engineering, especially in reactive and event-driven systems.</p>
<h2 id="heading-the-problem-it-solves">The Problem It Solves</h2>
<p>Let's look at what happens without the Observer pattern.</p>
<p>Say you have a login feature. When login succeeds, you need to do four things:</p>
<ul>
<li><p>Save the authentication token to secure storage</p>
</li>
<li><p>Cache the user profile data</p>
</li>
<li><p>Navigate to the home screen</p>
</li>
<li><p>Fire an analytics event</p>
</li>
</ul>
<p>The straightforward approach puts all of this inside the login function:</p>
<pre><code class="language-dart">Future&lt;void&gt; login(String email, String password) async {
  final response = await _authRepository.login(email, password);

  await _secureStorage.write(key: 'token', value: response.token);
  await _userCache.save(response.user);
  _navigationService.navigateTo('/home');
  _analytics.track('login_success', {'userId': response.user.id});
}
</code></pre>
<p>This looks fine at first glance. But count how many reasons this single function has to change:</p>
<ul>
<li><p>The token storage strategy changes. You modify this function.</p>
</li>
<li><p>The navigation destination changes. You modify this function.</p>
</li>
<li><p>The analytics event name or payload changes. You modify this function.</p>
</li>
<li><p>The user caching logic changes. You modify this function.</p>
</li>
</ul>
<p>Every single change to any of these four concerns forces you back into this one function. And every time you touch it, you risk breaking all the other three things it's doing.</p>
<p>Now imagine you need to add a fifth thing, such as enrolling the user in push notifications. You open this function again. You add more code. The function grows. Testing it requires mocking four, then five different dependencies. New teammates struggle to understand what this function is actually responsible for. The answer, of course, is everything. And that's the problem.</p>
<p>This is called tight coupling. The login logic is coupled to every single consequence of a successful login.</p>
<p>The Observer pattern breaks these couplings completely. The login logic does one thing: it performs the login and announces the result. Every consequence is handled by a separate, independent observer. Each observer has one job. None of them know about each other. The login logic doesn't know they exist.</p>
<h2 id="heading-core-components">Core Components</h2>
<p>The Observer pattern has four core building blocks. Understanding each one before writing code makes the implementation much easier to follow.</p>
<h3 id="heading-subject">Subject</h3>
<p>The Subject is the object that something happens to. It holds a list of observers and is responsible for notifying them when an event occurs. It exposes methods for observers to register and unregister themselves. The Subject doesn't care what observers do with the notification. It just delivers it.</p>
<h3 id="heading-observer">Observer</h3>
<p>The Observer is an interface or abstract class that defines the contract all observers must follow. It declares the method or methods the Subject will call when notifying. Any class that wants to react to an event must implement this interface.</p>
<h3 id="heading-concrete-subject">Concrete Subject</h3>
<p>The Concrete Subject is the real implementation of the Subject. It manages the actual list of observers, handles subscriptions, and fires notifications at the right moment.</p>
<h3 id="heading-concrete-observers">Concrete Observers</h3>
<p>These are the real classes that implement the Observer interface. Each one has a specific, focused job to do when notified. One saves the token. One navigates. One fires analytics. They don't know about each other and don't need to.</p>
<p>Here's how they relate to each other:</p>
<pre><code class="language-cpp">Subject (LoginService)
    |
    |-- subscribe(observer)    &lt;- observer registers itself
    |-- unsubscribe(observer)  &lt;- observer removes itself
    |-- notifySuccess(data)    &lt;- fires when login succeeds
    |-- notifyFailure(error)   &lt;- fires when login fails
         |
         |-----&gt; TokenObserver.onLoginSuccess()
         |-----&gt; UserObserver.onLoginSuccess()
         |-----&gt; NavigationObserver.onLoginSuccess()
         |-----&gt; AnalyticsObserver.onLoginSuccess()
</code></pre>
<p>The Subject notifies all of them. They each handle their own job independently.</p>
<h2 id="heading-implementing-observer-in-dart">Implementing Observer in Dart</h2>
<p>Let's build the pattern step by step.</p>
<h3 id="heading-step-1-define-the-observer-interface">Step 1: Define the Observer Interface</h3>
<pre><code class="language-dart">abstract class LoginObserver {
  void onLoginSuccess(UserDto user);
  void onLoginFailed(AppException error);
}
</code></pre>
<p>This is the contract that every observer must sign. Any class that wants to react to login events must implement both of these methods.</p>
<p><code>onLoginSuccess</code> is called when the login succeeds and receives the user data. <code>onLoginFailed</code> is called when the login fails and receives the error.</p>
<h3 id="heading-step-2-define-the-subject-interface">Step 2: Define the Subject Interface</h3>
<pre><code class="language-dart">abstract class LoginSubject {
  void subscribe(LoginObserver observer);
  void unsubscribe(LoginObserver observer);
  void notifySuccess(UserDto user);
  void notifyFailure(AppException error);
}
</code></pre>
<p><code>subscribe</code> lets an observer join the notification list. <code>unsubscribe</code> lets an observer leave the notification list. <code>notifySuccess</code> broadcasts a success event with the user data to all registered observers. <code>notifyFailure</code> broadcasts a failure event with the error to all registered observers.</p>
<p>Defining this as an abstract class instead of going straight to a concrete class is important. It means anything that depends on the subject depends on the abstraction, not the implementation. This makes your code testable and swappable.</p>
<h3 id="heading-step-3-implement-the-concrete-subject">Step 3: Implement the Concrete Subject</h3>
<pre><code class="language-dart">class LoginService implements LoginSubject {
  final List&lt;LoginObserver&gt; _observers = [];

  @override
  void subscribe(LoginObserver observer) {
    _observers.add(observer);
  }

  @override
  void unsubscribe(LoginObserver observer) {
    _observers.remove(observer);
  }

  @override
  void notifySuccess(UserDto user) {
    for (final observer in List.of(_observers)) {
      try {
        observer.onLoginSuccess(user);
      } catch (e) {
        debugPrint('Observer error on success: $e');
      }
    }
  }

  @override
  void notifyFailure(AppException error) {
    for (final observer in List.of(_observers)) {
      try {
        observer.onLoginFailed(error);
      } catch (e) {
        debugPrint('Observer error on failure: $e');
      }
    }
  }
}
</code></pre>
<p>There are two important decisions in this implementation that are easy to miss.</p>
<h4 id="heading-1-snapshot-iteration-with-listof">1. Snapshot iteration with <code>List.of()</code></h4>
<p>Instead of iterating directly over <code>_observers</code>, we iterate over <code>List.of(_observers)</code>, which creates a copy of the list before the loop runs.</p>
<p>Why does this matter? Imagine a <code>NavigationObserver</code> that, after navigating to the home screen, unsubscribes itself because it no longer needs to listen. If it calls <code>unsubscribe</code> while the <code>notifySuccess</code> loop is still running over the same list, Dart throws a <code>ConcurrentModificationError</code>. The list is being modified while it's being read.</p>
<p><code>List.of()</code> prevents this entirely. The loop runs over the snapshot. The original list can be modified freely during iteration without any errors.</p>
<h4 id="heading-2-per-observer-trycatch">2. Per-observer try/catch</h4>
<p>Each observer call is wrapped in its own try/catch block. This is a deliberate choice. If <code>TokenObserver</code> throws an exception while writing to secure storage, you don't want <code>NavigationObserver</code> and <code>AnalyticsObserver</code> to silently never fire. Each observer gets its chance to run regardless of what the others do.</p>
<p>Without this, one failing observer would stop the entire notification chain. That's a hidden bug that's extremely difficult to trace in production.</p>
<h2 id="heading-a-real-world-example-the-login-flow">A Real-World Example: The Login Flow</h2>
<p>Now let's build the full login flow using this foundation.</p>
<h3 id="heading-the-login-logic">The Login Logic</h3>
<pre><code class="language-cpp">class LoginLogic {
  final LoginSubject _subject;
  final AuthRepository _repository;

  LoginLogic({
    required LoginSubject subject,
    required AuthRepository repository,
  })  : _subject = subject,
        _repository = repository;

  Future&lt;void&gt; callLogin(LoginRequest request) async {
    try {
      final user = await _repository.login(request);
      _subject.notifySuccess(user);
    } on AppException catch (e) {
      _subject.notifyFailure(e);
    } catch (e) {
      _subject.notifyFailure(AppException.unknown(message: e.toString()));
    }
  }
}
</code></pre>
<p>Let's walk through this carefully.</p>
<p><code>LoginLogic</code> takes two dependencies through its constructor: a <code>LoginSubject</code> and an <code>AuthRepository</code>. Notice it takes <code>LoginSubject</code>, the abstraction, not <code>LoginService</code>, the concrete class. This means you can swap the implementation in tests or in different environments without changing <code>LoginLogic</code> at all.</p>
<p>Inside <code>callLogin</code>, the logic is straightforward. It calls the repository to perform the actual login. If that succeeds, it calls <code>notifySuccess</code> on the subject with the returned user. If it throws an <code>AppException</code>, it calls <code>notifyFailure</code> with that error. If it throws anything unexpected, it wraps it in an <code>AppException.unknown</code> and notifies failure.</p>
<p>Notice what <code>LoginLogic</code> does NOT do. It doesn't save a token. It doesn't navigate anywhere. It doesn't cache anything. It doesn't fire analytics. And it doesn't know how many observers exist or what they do.</p>
<p>Its entire responsibility is: perform the login, announce the result.</p>
<h3 id="heading-the-concrete-observers">The Concrete Observers</h3>
<pre><code class="language-cpp">class TokenObserver implements LoginObserver {
  final SecureStorageService _storage;

  TokenObserver(this._storage);

  @override
  void onLoginSuccess(UserDto user) {
    _storage.write(key: 'auth_token', value: user.token);
  }

  @override
  void onLoginFailed(AppException error) {
    _storage.delete(key: 'auth_token');
  }
}
</code></pre>
<p><code>TokenObserver</code> has one job: manage the authentication token. On success, it saves the token. On failure, it clears any stale token that might be sitting in storage. It knows nothing about navigation, caching, or analytics.</p>
<pre><code class="language-cpp">class UserObserver implements LoginObserver {
  final UserCacheService _cache;

  UserObserver(this._cache);

  @override
  void onLoginSuccess(UserDto user) {
    _cache.save(user);
  }

  @override
  void onLoginFailed(AppException error) {
    _cache.clear();
  }
}
</code></pre>
<p><code>UserObserver</code> has one job: manage the user cache. On success, it saves the user profile. On failure, it clears the cache. It knows nothing about tokens, navigation, or analytics.</p>
<pre><code class="language-cpp">class NavigationObserver implements LoginObserver {
  final NavigationService _navigation;

  NavigationObserver(this._navigation);

  @override
  void onLoginSuccess(UserDto user) {
    _navigation.navigateTo('/home');
  }

  @override
  void onLoginFailed(AppException error) {
    _navigation.showError(error.message);
  }
}
</code></pre>
<p><code>NavigationObserver</code> has one job: handle navigation after a login attempt. It uses an injected <code>NavigationService</code> abstraction rather than a <code>BuildContext</code>. This is intentional. An observer that depends on <code>BuildContext</code> is tied to the widget lifecycle. Using an abstraction keeps this observer completely independent of the UI layer.</p>
<pre><code class="language-cpp">class AnalyticsObserver implements LoginObserver {
  final AnalyticsService _analytics;

  AnalyticsObserver(this._analytics);

  @override
  void onLoginSuccess(UserDto user) {
    _analytics.track('login_success', {'userId': user.id});
  }

  @override
  void onLoginFailed(AppException error) {
    _analytics.track('login_failed', {'reason': error.message});
  }
}
</code></pre>
<p><code>AnalyticsObserver</code> has one job: fire the right analytics event for each outcome. It has no knowledge of storage, navigation, or caching.</p>
<p>Each observer has exactly one responsibility. Each one has exactly one reason to change. When the analytics payload needs to change, you touch only <code>AnalyticsObserver</code>. When navigation logic changes, you touch only <code>NavigationObserver</code>. Nothing else is affected.</p>
<h3 id="heading-wiring-it-together">Wiring It Together</h3>
<pre><code class="language-cpp">void setupLogin() {
  final service = LoginService();

  service
    ..subscribe(TokenObserver(secureStorage))
    ..subscribe(UserObserver(userCache))
    ..subscribe(NavigationObserver(navigationService))
    ..subscribe(AnalyticsObserver(analyticsService));

  final loginLogic = LoginLogic(
    subject: service,
    repository: authRepository,
  );
}
</code></pre>
<p>This is the composition step. All observers are created with their dependencies and registered onto the service. The cascade operator <code>..</code> calls <code>subscribe</code> multiple times on the same <code>service</code> object, which keeps the setup readable.</p>
<p><code>LoginLogic</code> receives the <code>service</code> as its <code>LoginSubject</code>. From this point forward, every time <code>callLogin</code> is called and an outcome occurs, all four observers are notified automatically.</p>
<p>Adding a fifth observer, say a <code>PushNotificationObserver</code>, means creating the class and adding one line here: <code>..subscribe(PushNotificationObserver(pushService))</code>. Nothing else in the entire codebase changes.</p>
<h2 id="heading-making-it-production-grade-with-a-generic-eventbus">Making It Production-Grade with a Generic EventBus</h2>
<p>The login example above works well, but it's specific to login. In a real application, many features have the same fan-out requirement. Payment confirmed, order placed, profile updated, session expired. All of them need one event to trigger multiple independent reactions.</p>
<p>Rewriting the Subject and Observer interfaces per feature is repetitive and unnecessary. The better approach is a generic <code>EventBus</code> that any feature can use.</p>
<pre><code class="language-cpp">abstract class DomainObserver&lt;T&gt; {
  void onSuccess(T data);
  void onFailure(AppException error);
}
</code></pre>
<p><code>DomainObserver&lt;T&gt;</code> is a generic observer. The type parameter <code>T</code> represents the data type the observer expects on success. A login observer would be <code>DomainObserver&lt;UserDto&gt;</code>. A payment observer would be <code>DomainObserver&lt;PaymentDto&gt;</code>. The interface is the same. The data type changes per feature.</p>
<pre><code class="language-cpp">class EventBus&lt;T&gt; {
  final List&lt;DomainObserver&lt;T&gt;&gt; _observers = [];

  void subscribe(DomainObserver&lt;T&gt; observer) {
    _observers.add(observer);
  }

  void unsubscribe(DomainObserver&lt;T&gt; observer) {
    _observers.remove(observer);
  }

  void publishSuccess(T data) {
    for (final observer in List.of(_observers)) {
      try {
        observer.onSuccess(data);
      } catch (e) {
        debugPrint('[EventBus] Observer error on success: $e');
      }
    }
  }

  void publishFailure(AppException error) {
    for (final observer in List.of(_observers)) {
      try {
        observer.onFailure(error);
      } catch (e) {
        debugPrint('[EventBus] Observer error on failure: $e');
      }
    }
  }
}
</code></pre>
<p><code>EventBus&lt;T&gt;</code> is a generic subject. It manages a list of typed observers and notifies them with the same snapshot iteration and per-observer error isolation we established earlier.</p>
<p>Now every feature gets the same infrastructure without duplicating a single line of the pattern:</p>
<pre><code class="language-cpp">final loginBus = EventBus&lt;UserDto&gt;();
final paymentBus = EventBus&lt;PaymentDto&gt;();
final orderBus = EventBus&lt;OrderDto&gt;();
</code></pre>
<p>Each bus is typed to its domain concept. Observers registered on <code>loginBus</code> will never accidentally receive payment events. The type system enforces correctness.</p>
<h2 id="heading-observer-is-already-in-your-flutter-code">Observer Is Already in Your Flutter Code</h2>
<p>Before going further into architecture, here's something worth pausing on. You've been using the Observer pattern all along without calling it by that name.</p>
<p><strong>Streams and StreamController:</strong></p>
<pre><code class="language-cpp">final controller = StreamController&lt;String&gt;();

controller.stream.listen((event) {
  print('Observed: $event');
});

controller.sink.add('Login succeeded');
</code></pre>
<p><code>StreamController</code> is a Subject. <code>stream.listen</code> is <code>subscribe</code>. <code>sink.add</code> is <code>notifyObservers</code>. Every stream subscription is an Observer. The pattern is identical. Flutter just gave it different names.</p>
<p><strong>ChangeNotifier:</strong></p>
<pre><code class="language-cpp">class CounterModel extends ChangeNotifier {
  int _count = 0;

  void increment() {
    _count++;
    notifyListeners();
  }
}
</code></pre>
<p><code>notifyListeners()</code> iterates over every registered listener and calls them. Those listeners are Observers. <code>addListener</code> is <code>subscribe</code>. <code>removeListener</code> is <code>unsubscribe</code>. <code>ChangeNotifier</code> is a concrete Subject.</p>
<p><strong>BLoC:</strong></p>
<p>When a BLoC emits a new state, every widget that wrapped itself in a <code>BlocBuilder</code> or <code>BlocListener</code> reacts. The BLoC is the Subject. The builders and listeners are Observers. The state emission is the notification.</p>
<p>Flutter's entire reactive system (Streams, ChangeNotifier, BLoC, ValueNotifier) is the Observer pattern with lifecycle management built in. Understanding the pattern at this fundamental level means you understand why all of these tools work the way they do. You aren't just using them. You understand them.</p>
<h2 id="heading-deep-dive-into-event-driven-architecture">Deep Dive Into Event-Driven Architecture</h2>
<p>Understanding Observer at the class level is the foundation. The pattern becomes significantly more powerful when applied at the architectural level, and that's where Event-Driven Architecture comes in.</p>
<h3 id="heading-what-is-event-driven-architecture">What is Event-Driven Architecture?</h3>
<p>Event-Driven Architecture is a design paradigm where the flow of the application is determined by events. Instead of components calling each other directly, they communicate by producing and consuming events through a shared bus or channel.</p>
<p>In a traditional request-driven flow, this is what happens:</p>
<pre><code class="language-cpp">Component A calls Component B directly
Component B does its work and returns a result
Component A waits for that result and then continues
</code></pre>
<p>Component A knows about Component B. It depends on it by name. It waits for it to finish. If you want Component C to also react to whatever Component A is doing, you have to go back into Component A and add that call.</p>
<p>But then Component A grows. Component A becomes responsible for orchestrating consequences it should know nothing about.</p>
<p>In an event-driven flow, this is what happens instead:</p>
<pre><code class="language-cpp">Component A publishes an event to the EventBus
EventBus delivers the event to whoever is registered

Component B handles the event
Component C handles the event
Component D handles the event
</code></pre>
<p>Component A doesn't know about B, C, or D. It doesn't wait for them. It publishes what happened and moves on. New handlers can be added without touching Component A at all. This is the Observer pattern scaled to the architectural level.</p>
<h3 id="heading-events-are-facts-not-commands">Events Are Facts, Not Commands</h3>
<p>This distinction is one of the most important concepts in Event-Driven Architecture.</p>
<p>A command says: "do this." It's an instruction that can be rejected. It expects a response.</p>
<p>An event says: "this happened." It's an immutable record of a fact. It doesn't expect a response. It doesn't care who handles it.</p>
<p><code>SaveUserToken</code> is a command. <code>UserLoggedIn</code> is an event.</p>
<p>When you model your system with events as facts, you get a historical record of everything that happened in your application. You can replay events to reconstruct state. You can add new handlers that process historical events. Your system becomes auditable and predictable in ways that command-driven systems are not.</p>
<h3 id="heading-modelling-domain-events-in-dart">Modelling Domain Events in Dart</h3>
<p>Events should be immutable value objects. They're facts. Facts don't change after they happen.</p>
<pre><code class="language-cpp">abstract class DomainEvent {
  final DateTime occurredAt;
  final String eventId;

  const DomainEvent({
    required this.occurredAt,
    required this.eventId,
  });
}
</code></pre>
<p><code>DomainEvent</code> is the base class for all events in the system. Every event has a timestamp (<code>occurredAt</code>) recording when it happened, and a unique identifier (<code>eventId</code>) for traceability.</p>
<pre><code class="language-cpp">class UserLoggedIn extends DomainEvent {
  final UserDto user;

  const UserLoggedIn({
    required this.user,
    required super.occurredAt,
    required super.eventId,
  });
}

class LoginFailed extends DomainEvent {
  final AppException error;

  const LoginFailed({
    required this.error,
    required super.occurredAt,
    required super.eventId,
  });
}
</code></pre>
<p><code>UserLoggedIn</code> carries the user data. <code>LoginFailed</code> carries the error. Both are immutable. Both have timestamps and identifiers. Both are concrete facts about something that happened in the domain.</p>
<h3 id="heading-a-type-safe-domaineventbus">A Type-Safe DomainEventBus</h3>
<p>Now we can build an event bus that's typed to domain events specifically:</p>
<pre><code class="language-cpp">abstract class EventHandler&lt;T extends DomainEvent&gt; {
  void handle(T event);
}
</code></pre>
<p><code>EventHandler&lt;T&gt;</code> is the Observer interface for this architecture. Any class that wants to handle a domain event implements this with the specific event type it cares about.</p>
<pre><code class="language-cpp">class DomainEventBus {
  final _handlers = &lt;Type, List&lt;EventHandler&gt;&gt;{};

  void register&lt;T extends DomainEvent&gt;(EventHandler&lt;T&gt; handler) {
    _handlers.putIfAbsent(T, () =&gt; []).add(handler);
  }

  void publish&lt;T extends DomainEvent&gt;(T event) {
    final handlers = List.of(_handlers[T] ?? []);
    for (final handler in handlers) {
      try {
        (handler as EventHandler&lt;T&gt;).handle(event);
      } catch (e) {
        debugPrint('[DomainEventBus] Handler error for ${T}: $e');
      }
    }
  }
}
</code></pre>
<p>Let's go through <code>DomainEventBus</code> carefully.</p>
<p><code>_handlers</code> is a map where the key is a <code>Type</code> (the event class itself, like <code>UserLoggedIn</code>) and the value is a list of all handlers registered for that event type.</p>
<p><code>register&lt;T&gt;</code> takes a handler and adds it to the list for type <code>T</code>. <code>putIfAbsent</code> ensures the list is created if this is the first handler for that event type.</p>
<p><code>publish&lt;T&gt;</code> looks up all handlers registered for the type of event being published and calls each one's <code>handle</code> method. The snapshot with <code>List.of()</code> and the per-handler try/catch are both present for the same reasons we established earlier.</p>
<p>Here's how you register handlers and publish events:</p>
<pre><code class="language-dart">// Registration happens once at startup
eventBus.register&lt;UserLoggedIn&gt;(TokenHandler(secureStorage));
eventBus.register&lt;UserLoggedIn&gt;(UserCacheHandler(userCache));
eventBus.register&lt;UserLoggedIn&gt;(NavigationHandler(navigationService));
eventBus.register&lt;UserLoggedIn&gt;(AnalyticsHandler(analyticsService));

eventBus.register&lt;PaymentConfirmed&gt;(ReceiptHandler(receiptService));
eventBus.register&lt;PaymentConfirmed&gt;(InventoryHandler(inventoryService));

// Publishing happens at the use case level
eventBus.publish(UserLoggedIn(
  user: user,
  occurredAt: DateTime.now(),
  eventId: const Uuid().v4(),
));
</code></pre>
<p>When <code>UserLoggedIn</code> is published, only its registered handlers fire. Payment handlers aren't touched. Every handler for <code>UserLoggedIn</code> runs independently with full error isolation.</p>
<h2 id="heading-application-in-domain-driven-design">Application in Domain-Driven Design</h2>
<p>Event-Driven Architecture and the Observer pattern find their most structured home inside Domain-Driven Design. DDD gives us the vocabulary and structure to know exactly where events belong, who creates them, and who handles them.</p>
<h3 id="heading-key-ddd-concepts-you-need-to-know">Key DDD Concepts You Need to Know</h3>
<p><strong>Domain Events</strong> are first-class citizens in DDD. They represent something meaningful that happened in the business domain. Not a technical detail, not an HTTP response, but a business fact.</p>
<p><code>UserLoggedIn</code> is a domain event. <code>LoginResponseDto</code> is a data transfer object. The distinction matters deeply. The event belongs to the domain model and expresses business language. The DTO belongs to the data layer and expresses data structure.</p>
<p><strong>Aggregates</strong> are the natural source of domain events. An Aggregate is a cluster of domain objects that form a consistency boundary. The Aggregate enforces business rules and raises domain events when significant state changes occur within it.</p>
<p><strong>Use Cases</strong> are the orchestrators. A use case calls the repository, gets the result, raises the appropriate domain event, and returns the outcome. It doesn't handle side effects directly. It announces what happened and lets the registered handlers take over.</p>
<h3 id="heading-where-everything-lives-in-clean-architecture">Where Everything Lives in Clean Architecture</h3>
<pre><code class="language-plaintext">lib/
  core/
    events/
      domain_event.dart           &lt;- Base DomainEvent class
      domain_event_bus.dart       &lt;- The DomainEventBus
      event_handler.dart          &lt;- Base EventHandler interface

  features/
    auth/
      domain/
        events/
          user_logged_in.dart     &lt;- Domain event (pure Dart, no Flutter)
          login_failed.dart       &lt;- Domain event
        handlers/
          token_handler.dart      &lt;- Handles token storage
          user_cache_handler.dart &lt;- Handles user caching
          analytics_handler.dart  &lt;- Handles analytics
        entities/
          user.dart
        repositories/
          auth_repository.dart    &lt;- Abstract interface only
        usecases/
          login_usecase.dart      &lt;- Orchestrates, publishes events

      data/
        repositories/
          auth_repository_impl.dart
        datasources/
          auth_remote_datasource.dart

      presentation/
        providers/
          login_provider.dart     &lt;- Riverpod notifier (thin)
        pages/
          login_page.dart
</code></pre>
<p>The critical rule: the domain layer is pure Dart. No Flutter imports. No Riverpod imports. No HTTP imports. The <code>DomainEventBus</code>, domain events, handlers, and use cases all live in the domain layer and have zero framework dependencies.</p>
<p>This means that the same domain logic works in Flutter, server-side Dart, or a CLI tool without changing a single line. Framework upgrades, say from Riverpod 2.x to a future version, never touch the domain. Unit tests for the domain run in milliseconds with no widget test overhead.</p>
<h3 id="heading-the-login-use-case-in-ddd">The Login Use Case in DDD</h3>
<pre><code class="language-cpp">class LoginUseCase {
  final AuthRepository _repository;
  final DomainEventBus _eventBus;

  LoginUseCase({
    required AuthRepository repository,
    required DomainEventBus eventBus,
  })  : _repository = repository,
        _eventBus = eventBus;

  Future&lt;Result&lt;UserDto, AppException&gt;&gt; execute(LoginRequest request) async {
    try {
      final user = await _repository.login(request);

      _eventBus.publish(UserLoggedIn(
        user: user,
        occurredAt: DateTime.now(),
        eventId: const Uuid().v4(),
      ));

      return Result.success(user);
    } on AppException catch (e) {
      _eventBus.publish(LoginFailed(
        error: e,
        occurredAt: DateTime.now(),
        eventId: const Uuid().v4(),
      ));

      return Result.failure(e);
    }
  }
}
</code></pre>
<p>Let's walk through this step by step.</p>
<p><code>LoginUseCase</code> receives two dependencies: an <code>AuthRepository</code> abstraction and a <code>DomainEventBus</code>. Neither is a concrete class. Both can be swapped in tests.</p>
<p>Inside <code>execute</code>, it calls the repository to perform the login. If the login succeeds, it publishes a <code>UserLoggedIn</code> event to the bus, which immediately notifies all registered handlers. Then it returns a <code>Result.success</code> wrapping the user data.</p>
<p>If an <code>AppException</code> is caught, it publishes a <code>LoginFailed</code> event to the bus, which notifies all failure handlers. Then it returns a <code>Result.failure</code> wrapping the error.</p>
<p>The use case doesn't know how many handlers are registered. It doesn't know what they do. It performs the operation, publishes the outcome as a domain event, and returns the result.</p>
<p>The <code>Result</code> type is a return value for the caller (the Riverpod notifier) to know the outcome. The domain event is the broadcast for all side effect handlers. Both travel from the same single use case call. This is what makes the architecture clean.</p>
<h2 id="heading-the-riverpod-hybrid-clean-architecture-in-practice">The Riverpod Hybrid: Clean Architecture in Practice</h2>
<p>This is where everything comes together in a real Flutter application.</p>
<h3 id="heading-the-problem-we-are-solving">The Problem We Are Solving</h3>
<p>There are two common pain points in Flutter apps that use Riverpod:</p>
<p>Fat ref.listen in widgets:</p>
<pre><code class="language-cpp">// This is messy
ref.listen&lt;AsyncValue&lt;UserDto?&gt;&gt;(loginProvider, (previous, next) {
  next.whenData((user) {
    if (user != null) {
      secureStorage.write(key: 'token', value: user.token);
      userCache.save(user);
      context.go('/home');
      analytics.track('login_success');
    }
  });
});
</code></pre>
<p>The widget is mounted. If it unmounts before all of this completes, some side effects may never run. Business consequences like token storage and navigation shouldn't depend on whether a widget is still alive. This is fragile architecture.</p>
<p>Fat notifiers:</p>
<pre><code class="language-dart">// Notifier doing too much
Future&lt;void&gt; login(LoginRequest request) async {
  state = const AsyncLoading();
  try {
    final user = await _loginUseCase.execute(request);
    await _secureStorage.write(key: 'token', value: user.token);
    await _userCache.save(user);
    _navigationService.navigateTo('/home');
    _analytics.track('login_success');
    state = AsyncData(user);
  } catch (e, st) {
    state = AsyncError(e, st);
  }
}
</code></pre>
<p>The notifier is violating the Single Responsibility Principle. It's performing the login, saving the token, caching the user, navigating, tracking analytics, and managing UI state. That's six responsibilities in one class. It's impossible to test cleanly and painful to maintain.</p>
<h3 id="heading-the-clean-rule">The Clean Rule</h3>
<p>Before looking at the solution, establish this rule clearly:</p>
<p><strong>The use case owns domain consequences. The notifier owns UI state. Widgets own nothing.</strong></p>
<p>The use case performs the operation and publishes domain events. Handlers fire when those events are published and run completely independently of the widget lifecycle. The notifier receives the result from the use case and emits loading, success, or error state so the UI knows what to display. Widgets read that state and render accordingly.</p>
<p>That's the full picture. And it means this architecture works correctly whether login is triggered from a widget, a biometric prompt, a deep link, or a background service. The use case always publishes. The handlers always fire. The notifier only deals with UI state.</p>
<h3 id="heading-understanding-asyncnotifier">Understanding AsyncNotifier</h3>
<p>Before writing the notifier, let's understand what <code>AsyncNotifier</code> is and how it works.</p>
<p><code>AsyncNotifier</code> is a Riverpod 2.0 class designed specifically for asynchronous state. It holds an <code>AsyncValue&lt;T&gt;</code>, which is a sealed type that can be one of three things:</p>
<p><code>AsyncData&lt;T&gt;</code> means the operation succeeded and data is available. <code>AsyncLoading</code> means an operation is in progress. <code>AsyncError</code> means an operation failed.</p>
<p>When you extend <code>AsyncNotifier&lt;T&gt;</code>, you implement a <code>build</code> method that returns the initial state, and you write methods that mutate <code>state</code> as async operations progress.</p>
<p>With code generation using <code>@riverpod</code>, you annotate your class and run <code>flutter pub run build_runner build</code>. The generator creates the provider and all the boilerplate automatically. You focus entirely on the logic.</p>
<p>Here's the full setup for code generation:</p>
<pre><code class="language-yaml"># pubspec.yaml
dependencies:
  flutter_riverpod: ^2.5.1
  riverpod_annotation: ^2.3.5

dev_dependencies:
  riverpod_generator: ^2.4.0
  build_runner: ^2.4.9
</code></pre>
<h3 id="heading-the-thin-notifier">The Thin Notifier</h3>
<pre><code class="language-cpp">// login_provider.dart
part 'login_provider.g.dart';

@riverpod
class LoginNotifier extends _$LoginNotifier {

  @override
  AsyncValue&lt;UserDto?&gt; build() {
    return const AsyncData(null);
  }

  Future&lt;void&gt; login(LoginRequest request) async {
    state = const AsyncLoading();

    final result = await ref.read(loginUseCaseProvider).execute(request);

    result.fold(
      onSuccess: (user) =&gt; state = AsyncData(user),
      onFailure: (error) =&gt; state = AsyncError(error, StackTrace.current),
    );
  }
}
</code></pre>
<p>Let's go through this line by line.</p>
<p><code>part 'login_provider.g.dart'</code> tells Dart that the generated file is part of this library. The <code>@riverpod</code> annotation and <code>_$LoginNotifier</code> base class come from the generated file.</p>
<p><code>build()</code> is the initialisation method. It runs when the provider is first read. It returns <code>AsyncData(null)</code>, meaning the initial state is a successful state with no user yet. This is correct because no login has been attempted.</p>
<p>Inside <code>login</code>, the first thing we do is set <code>state = const AsyncLoading()</code>. This immediately notifies any widget watching this provider that an operation is in progress. The UI can show a loading indicator.</p>
<p>We then call the use case and <code>await</code> its result. The use case returns a <code>Result&lt;UserDto, AppException&gt;</code>, which is a type that holds either a success value or a failure value, never both. We call <code>fold</code> on it to handle each case.</p>
<p>In the <code>onSuccess</code> branch, we set <code>state = AsyncData(user)</code>. This tells the UI the operation succeeded and here is the user data to render.</p>
<p>In the <code>onFailure</code> branch, we set <code>state = AsyncError(error, StackTrace.current)</code>. This tells the UI something went wrong so it can display the appropriate error state.</p>
<p>That's the entire notifier. It does exactly one thing: reflect the outcome of the use case as UI state.</p>
<p>Notice there's no token saving here. No navigation, caching, or analytics. All of that is already handled. The moment the use case called <code>_eventBus.publish(UserLoggedIn(...))</code> inside <code>execute</code>, every registered handler fired automatically. By the time <code>result</code> is returned to this notifier, all side effects are already done. The notifier just needs to update the UI.</p>
<p>This is the cleanest possible separation. The use case owns domain consequences. The notifier owns render state. Each has exactly one responsibility.</p>
<h3 id="heading-the-widget">The Widget</h3>
<pre><code class="language-cpp">class LoginPage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final loginState = ref.watch(loginNotifierProvider);

    return Scaffold(
      body: loginState.when(
        data: (_) =&gt; const LoginForm(),
        loading: () =&gt; const Center(child: CircularProgressIndicator()),
        error: (error, _) =&gt; ErrorView(message: error.toString()),
      ),
    );
  }
}

class LoginForm extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () {
            ref.read(loginNotifierProvider.notifier).login(
              LoginRequest(email: 'user@example.com', password: 'secret'),
            );
          },
          child: const Text('Login'),
        ),
      ],
    );
  }
}
</code></pre>
<p><code>ref.watch(loginNotifierProvider)</code> subscribes this widget to the notifier's state. Every time <code>state</code> changes inside the notifier, <code>build</code> is called again and the widget re-renders.</p>
<p><code>loginState.when</code> is how you handle each case of <code>AsyncValue</code>. When the state is <code>AsyncData</code>, it renders the login form. When it is <code>AsyncLoading</code>, it renders a loading indicator. When it is <code>AsyncError</code>, it renders the error view.</p>
<p>The widget knows nothing about tokens, navigation, or caching. It renders what it's told to render by the state. That's its entire job.</p>
<h3 id="heading-wiring-the-composition-root">Wiring the Composition Root</h3>
<p>All handler registrations happen once at app startup inside a Riverpod provider:</p>
<pre><code class="language-cpp">@riverpod
DomainEventBus eventBus(EventBusRef ref) {
  final bus = DomainEventBus();

  bus.register&lt;UserLoggedIn&gt;(
    TokenHandler(ref.read(secureStorageProvider)),
  );
  bus.register&lt;UserLoggedIn&gt;(
    UserCacheHandler(ref.read(userCacheProvider)),
  );
  bus.register&lt;UserLoggedIn&gt;(
    NavigationHandler(ref.read(navigationServiceProvider)),
  );
  bus.register&lt;UserLoggedIn&gt;(
    AnalyticsHandler(ref.read(analyticsServiceProvider)),
  );

  bus.register&lt;LoginFailed&gt;(
    AnalyticsFailureHandler(ref.read(analyticsServiceProvider)),
  );

  return bus;
}
</code></pre>
<p><code>eventBus</code> is a provider that creates the <code>DomainEventBus</code> and registers all handlers at the moment it is first read. Because Riverpod providers are lazy by default and cached after first creation, this runs once and the bus lives for the entire app session.</p>
<p>Every handler gets its dependencies injected via <code>ref.read</code>. Nothing is hardcoded. Everything is swappable in tests.</p>
<p>The <code>LoginUseCase</code> receives this event bus as a dependency through its own provider:</p>
<pre><code class="language-cpp">@riverpod
LoginUseCase loginUseCase(LoginUseCaseRef ref) {
  return LoginUseCase(
    repository: ref.read(authRepositoryProvider),
    eventBus: ref.read(eventBusProvider),
  );
}
</code></pre>
<p>This is the only place that connects the use case to the event bus. The notifier receives only the use case. The widget receives only the notifier's state. Each layer knows only about the layer directly below it and nothing else.</p>
<p>Adding a new side effect to login means creating a new handler class and adding one <code>bus.register</code> line in the composition root. The notifier, the use case logic, the widget, and every existing handler remain completely untouched.</p>
<h2 id="heading-testing-the-observer-architecture">Testing the Observer Architecture</h2>
<p>One of the most significant advantages of this architecture is how clearly it separates test concerns. Each layer has its own focused test scope.</p>
<h3 id="heading-testing-the-use-case">Testing the Use Case</h3>
<pre><code class="language-cpp">void main() {
  group('LoginUseCase', () {
    late LoginUseCase useCase;
    late MockAuthRepository mockRepository;
    late MockDomainEventBus mockEventBus;

    setUp(() {
      mockRepository = MockAuthRepository();
      mockEventBus = MockDomainEventBus();
      useCase = LoginUseCase(
        repository: mockRepository,
        eventBus: mockEventBus,
      );
    });

    test('publishes UserLoggedIn event on success', () async {
      final user = UserDto(id: '1', token: 'token123');
      when(() =&gt; mockRepository.login(any())).thenAnswer((_) async =&gt; user);

      await useCase.execute(LoginRequest(email: 'a@b.com', password: '123'));

      verify(() =&gt; mockEventBus.publish(any&lt;UserLoggedIn&gt;())).called(1);
    });

    test('publishes LoginFailed event on error', () async {
      when(() =&gt; mockRepository.login(any()))
          .thenThrow(AppException.unauthorized(message: 'Invalid credentials'));

      await useCase.execute(LoginRequest(email: 'a@b.com', password: 'wrong'));

      verify(() =&gt; mockEventBus.publish(any&lt;LoginFailed&gt;())).called(1);
    });
  });
}
</code></pre>
<p>The use case test mocks the repository and the event bus. It verifies that the correct event type was published for each outcome. It doesn't test what any handler does. That's not the use case's responsibility, so it's not the use case's test.</p>
<h3 id="heading-testing-each-handler">Testing Each Handler</h3>
<pre><code class="language-cpp">void main() {
  group('TokenHandler', () {
    late TokenHandler handler;
    late MockSecureStorageService mockStorage;

    setUp(() {
      mockStorage = MockSecureStorageService();
      handler = TokenHandler(mockStorage);
    });

    test('writes token to secure storage on UserLoggedIn', () {
      final event = UserLoggedIn(
        user: UserDto(id: '1', token: 'abc123'),
        occurredAt: DateTime.now(),
        eventId: 'event-1',
      );

      handler.handle(event);

      verify(
        () =&gt; mockStorage.write(key: 'auth_token', value: 'abc123'),
      ).called(1);
    });
  });
}
</code></pre>
<p>Each handler test is tiny. It creates the handler with a mocked dependency, fires the event, and verifies the exact side effect that handler is responsible for. No other handler is involved, no notifier is involved, and no widget is involved.</p>
<h3 id="heading-testing-the-notifier">Testing the Notifier</h3>
<pre><code class="language-cpp">void main() {
  group('LoginNotifier', () {
    test('transitions from loading to data on success', () async {
      final mockUseCase = MockLoginUseCase();
      final user = UserDto(id: '1', token: 'token123');

      when(() =&gt; mockUseCase.execute(any()))
          .thenAnswer((_) async =&gt; Result.success(user));

      final container = ProviderContainer(overrides: [
        loginUseCaseProvider.overrideWithValue(mockUseCase),
      ]);

      final notifier = container.read(loginNotifierProvider.notifier);

      await notifier.login(LoginRequest(email: 'a@b.com', password: '123'));

      expect(
        container.read(loginNotifierProvider),
        isA&lt;AsyncData&lt;UserDto?&gt;&gt;(),
      );
    });

    test('transitions from loading to error on failure', () async {
      final mockUseCase = MockLoginUseCase();
      final error = AppException.unauthorized(message: 'Invalid credentials');

      when(() =&gt; mockUseCase.execute(any()))
          .thenAnswer((_) async =&gt; Result.failure(error));

      final container = ProviderContainer(overrides: [
        loginUseCaseProvider.overrideWithValue(mockUseCase),
      ]);

      final notifier = container.read(loginNotifierProvider.notifier);

      await notifier.login(LoginRequest(email: 'a@b.com', password: 'wrong'));

      expect(
        container.read(loginNotifierProvider),
        isA&lt;AsyncError&gt;(),
      );
    });
  });
}
</code></pre>
<p>The notifier test only verifies state transitions. It doesn't need to mock the event bus because the notifier no longer touches the event bus. That's the use case's job, and the use case has its own test that verifies events are published correctly. Each layer is tested in complete isolation with no overlap.</p>
<h2 id="heading-when-to-use-the-observer-pattern">When to Use the Observer Pattern</h2>
<p>Use Observer when:</p>
<ul>
<li><p>One event needs to trigger multiple independent reactions</p>
</li>
<li><p>You want to add or remove reactions without modifying the event source</p>
</li>
<li><p>Side effects need to be decoupled from business logic</p>
</li>
<li><p>Each reaction should be independently testable</p>
</li>
<li><p>Multiple parts of the system need to react to the same state change</p>
</li>
<li><p>You are building a feature that will grow in number of side effects over time</p>
</li>
</ul>
<h2 id="heading-when-not-to-use-it">When Not to Use It</h2>
<p>Avoid Observer when:</p>
<ul>
<li><p>You have only one consumer and no realistic expectation of more</p>
</li>
<li><p>The relationship between producer and consumer is simple and direct</p>
</li>
<li><p>The pattern adds structural overhead without meaningful benefit</p>
</li>
<li><p>Streams, ChangeNotifier, or Riverpod's built-in reactivity already solve the problem naturally</p>
</li>
<li><p>Strict ordering of side effects is critical and fan-out makes that hard to guarantee</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The Observer Design Pattern is one of the most important tools in a software engineer's arsenal. This isn't because it's clever, but because it solves a problem every growing application faces: how do you let one event trigger many reactions without turning your codebase into a tightly coupled mess?</p>
<p>You started by understanding the pattern at its core. A Subject holds a list of Observers and notifies them when events occur. You saw it built step by step in Dart, with snapshot iteration to prevent concurrent modification errors, per-observer try/catch to prevent failure cascades, and dependency inversion to keep everything testable.</p>
<p>You discovered that the Observer pattern is already embedded in Flutter's Streams, ChangeNotifier, and BLoC. Understanding its foundations means you understand why those tools work the way they do.</p>
<p>You then took the pattern into Event-Driven Architecture, where events become immutable domain facts and the system is composed of producers and consumers with no direct coupling between them.</p>
<p>You applied it inside Domain-Driven Design, giving events a proper home in a pure Dart domain layer that is framework-independent, fully portable, and fully testable.</p>
<p>And you saw how it integrates with Riverpod through a hybrid architecture with a clear and enforced rule: handlers own side effects, the notifier owns UI state, and widgets own nothing.</p>
<p>The result is a codebase that scales gracefully. When a new side effect needs to be added, you create one handler and register it in one place. Nothing else changes. That's the promise of the Observer pattern. And as you've seen throughout this handbook, it's a promise it keeps.</p>
<p>Happy Coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Sacrificial Architecture – How to Make Tough Decisions to Abandon and Rebuild Systems ]]>
                </title>
                <description>
                    <![CDATA[ By Nahla Davies When you're working with an application, sometimes it no longer makes sense to try to continue and improve what already exists. Instead, you need to rethink, restructure, and rebuild.  Making the decision to give up all the work you a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/sacrificial-architecture-make-tough-decisions-to-abandon-and-rebuild-systems/</link>
                <guid isPermaLink="false">66d4604b7df3a1f32ee7f879</guid>
                
                    <category>
                        <![CDATA[ Clean Architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 24 Aug 2021 19:02:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/pexels-wendelin-jacober-1411400.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Nahla Davies</p>
<p>When you're working with an application, sometimes it no longer makes sense to try to continue and improve what already exists. Instead, you need to rethink, restructure, and rebuild. </p>
<p>Making the decision to give up all the work you and others have put into the existing system is a difficult choice for many developers. Still, dogged devotion to existing code in the face of disruption is a disservice to developers and users alike.</p>
<p>The effects of any large-scale alterations to a system reach far beyond the development world. Wholesale system replacements are rarely invisible, which also makes life difficult for salespeople and marketers. They're the ones who have to explain to customers why such a drastic change happened. </p>
<p>But this does not make the changes any less necessary.</p>
<p>As with so many other things in life, just because a choice is difficult and painful does not mean it is wrong. Evolution can be a violent process. But failure to adapt leads to extinction. </p>
<p>When fish crawled out of the sea millions of years ago, they didn’t continue to improve on fins and gills. Entirely new systems were necessary for motion and breathing. It doesn’t mean that fins and gills weren’t valuable or that their design was flawed. Indeed, their designs fit perfectly with their intended purposes. But the purpose became irrelevant, and so they were no longer suitable in their current environment. </p>
<p>When the time comes (and it will), you must step back and take an objective look at the situation. Will another tweak to that fin work? Or will it just highlight how poorly adapted it is to current needs?</p>
<h2 id="heading-intelligent-design-choice-or-inevitable-reaction">Intelligent Design Choice or Inevitable Reaction?</h2>
<p>Much of the discussion on sacrificial architecture revolves around whether it should be a proactive development process as opposed to a last-ditch reactionary decision. </p>
<p>Should developers intentionally build systems with limited lifetimes? Or should they build for the long run and make large-scale changes only if absolutely necessary?</p>
<p>According to Martin Fowler, who <a target="_blank" href="https://www.infoq.com/news/2014/11/sacrificial-architecture/">introduced sacrificial architecture seven years ago</a>, building it into the design process can be a good idea:</p>
<blockquote>
<p><em>“So what does it mean to deliberately choose a sacrificial architecture? Essentially it means accepting now that, in a few years’ time, you'll (hopefully) need to throw away what you're currently building.</em>   </p>
<p><em>This can mean accepting limits to the cross-functional needs of what you're putting together. It can mean thinking now about things that can make it easier to replace when the time comes - software designers rarely think about how to design their creation to support its graceful replacement. It also means recognizing that software that's thrown away in a relatively short time can still deliver plenty of value.”</em></p>
</blockquote>
<p>Intentional sacrifice can also be useful when considering new features or applications as a way to limit overall development effort. </p>
<p>Using sacrificial architecture for proof-of-concept systems can move the development process more quickly towards a launchable implementation. As noted in <a target="_blank" href="https://pubs.opengroup.org/architecture/o-aaf/snapshot/Agile_Architecture_Framework.html">the Open Group Agile Architecture Framework</a>:</p>
<blockquote>
<p><em>“When the goal is to get rapid market feedback experimenting with an MVP, sacrificial architecture is an option to consider as it would not be worth spending too much time designing an architecture that would have to change should the product owner decide to pivot.”</em></p>
</blockquote>
<p>This is not to say that proactively using sacrificial architecture will eliminate the need for reactive sacrifices. There are always going to be changes and disruptions that you and your team will not anticipate. And disruptions often lead to sacrifices and evolutions. </p>
<p>Just consider how the COVID pandemic crisis disrupted so many aspects of everyday life, from how employees work to <a target="_blank" href="https://www.freecodecamp.org/news/disrupting-the-status-quo-of-traditional-learning-ef83c694cfd7/">how schools teach our children</a>.</p>
<p>There are many less drastic examples as well. One side effect of the COVID crisis was the rapid acceleration of e-commerce business and online transactions. </p>
<p>But the industry had to adapt to rising consumer concerns about data privacy. All online businesses rely on software with crucial features such as online invoicing and payments. But application providers and payment processors had to rapidly adapt existing systems to ensure compliance with new standards like the Payment Card Data Security Standard (PCI-DSS) and the European Union General Data Protection Regulation (GDPR). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-179.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://interestingengineering.com/best-youtube-channels-for-coding-and-programming">Image Source</a></em></p>
<p>In the same way, code can become obsolete or fail to accomplish its intended purposes. There are times when disruptions in coding practices or programming language capabilities mean that you need to make large-scale changes. </p>
<p>Just consider eBay, which has changed its underlying programming language twice since its founding in 1995. Why? Because the capabilities of the abandoned languages failed to meet eBay’s needs and requirements as the business grew.</p>
<h2 id="heading-how-to-anticipate-the-sacrifice">How to Anticipate the Sacrifice</h2>
<p>Developers cannot possibly build to avoid the need for replacements altogether, and they shouldn’t focus on doing so. There are, however, steps you can take to plan for obsolescence.</p>
<h3 id="heading-build-with-replacement-in-mind">Build with replacement in mind</h3>
<p>As Fowler stated, you can build code with the idea that it will require replacement in a few years. Outdated code will eventually become susceptible to malicious viruses that could result in browser hijacking or system slowdowns. </p>
<p>This means that you need to consider in advance the code’s limitations, including performance and scalability, and other characteristics.</p>
<h3 id="heading-minimize-sacrifice-through-modularity">Minimize sacrifice through modularity</h3>
<p>As a general rule, it is easier to replace smaller pieces of code than it is to replace an entire structure. </p>
<p>Just as you don’t need to spend the time and money to replace your entire roof if a shingle gets blown off, there is no need to completely rewrite the code for a system if revising one module will do. </p>
<p>So building modular code results in an architecture <a target="_blank" href="https://stackoverflow.blog/2021/03/08/infrastructure-as-code-create-and-configure-infrastructure-elements-in-seconds/">that is easier for developers</a> to modify as needed.</p>
<p>But modularity is not always an effective solution, and you should be aware of the limits of your code. Sometimes, replacing too many pieces can weaken a structure or make it unstable. </p>
<p>In the same way, the more modules you replace in your existing code, the more opportunities there are for problems with the operation of the code as a whole. That is the dividing line between continued piece-by-piece updating and wholesale replacement.</p>
<h3 id="heading-maintain-quality-standards">Maintain quality standards</h3>
<p>Even when you intentionally decide to build code knowing you will sacrifice it in the near future, you should always continjue to strive to meet or exceed company quality standards. After all, the sacrificial architecture will still probably be in production. </p>
<p>Needs may also change, eliminating the reasons that you planned to retire the code in the first place. Poorly designed or implemented code also <a target="_blank" href="https://www.freecodecamp.org/news/clean-coding-for-beginners/">makes developers’ lives more difficult</a> when modifying the code. </p>
<p>Poor documentation and code structure also hinder your ability to understand the connections between pieces of code, making replacements and updates more challenging. </p>
<p>Poorly designed code can <a target="_blank" href="https://hostingdata.co.uk/online-privacy-guide/">also be a significant security risk</a>, perhaps allowing hackers to access private data that companies have invested so much to protect.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/06/image-180.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.altexsoft.com/blog/business/technical-documentation-in-software-development-types-best-practices-and-tools/">Image Source</a></em></p>
<p>Quality is a mantra that must always be front-of-mind, even for disposable code.</p>
<h2 id="heading-sacrificing-for-the-greater-good">Sacrificing for the Greater Good</h2>
<p>While it may sound trite to quote this common saying, sacrificing your code may indeed be for the greater good of your systems and your company in the long run. </p>
<p>Judicious, proactive use of sacrificial architectures can help reduce time to market for new features. And, it can minimize how much effort it takes when an unplanned, large-scale replacement inevitably occurs.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Modern Clean Architecture ]]>
                </title>
                <description>
                    <![CDATA[ By Bertil Muth Clean Architecture is a term coined by Robert C. Martin. The main idea is that entities and use cases are independent of frameworks, UI, the database, and external services. A Clean Architecture style has a positive effect on maintaina... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/modern-clean-architecture/</link>
                <guid isPermaLink="false">66d45de44a7504b7409c3355</guid>
                
                    <category>
                        <![CDATA[ Clean Architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clean code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 12 Aug 2021 15:28:31 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/300px-Guggenheim-New_York-interior-20060717.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Bertil Muth</p>
<p><a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">Clean Architecture</a> is a term coined by Robert C. Martin. The main idea is that entities and use cases are independent of frameworks, UI, the database, and external services.</p>
<p>A Clean Architecture style has a positive effect on maintainability because:</p>
<ul>
<li>We can test domain entities and use cases without a framework, UI, or infrastructure.</li>
<li>Technology decisions can change without affecting domain code, and vice versa. It is even possible to switch to a new framework with limited effort.</li>
</ul>
<p>My goal is to flatten the learning curve, and reduce the effort it might take you to implement a Clean Architecture. That’s why I created the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture">Modern Clean Architecture</a> libraries.</p>
<p>In this article, I will show you how to create an application with a modern clean architecture, from a HTML/JavaScript front end to a Spring Boot back end. The focus will be on the back end.</p>
<p>Let’s start with an overview of the sample application – a timeless classic, the TODO app.</p>
<h2 id="heading-sample-todo-list-application">Sample TODO List Application</h2>
<p>A <em>to do list</em> is a collection of <em>tasks</em>. A task has a <em>name</em>, and is either <em>completed</em> or not. As a user, you can:</p>
<ul>
<li>Create a single to do list, and persist it</li>
<li>Add a task</li>
<li>Complete a task, or “uncomplete” it</li>
<li>Delete a task</li>
<li>List all tasks</li>
<li>Filter completed/uncompleted tasks</li>
</ul>
<p>Here’s what a todo list with 1 uncompleted and 2 completed tasks looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/grafik-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We'll start at the core of the application, the domain entities. Then we'll work our way outwards to the front end.</p>
<h2 id="heading-the-domain-entities">The Domain Entities</h2>
<p>The central domain entities are <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/domain/TodoList.java">TodoList</a> and <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/domain/Task.java">Task</a>.</p>
<p>The <em>TodoList</em> entity contains:</p>
<ul>
<li>a unique id,</li>
<li>a list of tasks,</li>
<li>domain methods for adding, completing, and deleting tasks</li>
</ul>
<p>The <code>TodoList</code> entity doesn’t contain public setters. Setters would break proper encapsulation.</p>
<p>Here’s part of the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/domain/TodoList.java">TodoList</a> entity. <a target="_blank" href="https://projectlombok.org/">Lombok</a> annotations shorten the code.</p>
<pre><code class="lang-Java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoList</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">AggregateRoot</span>&lt;<span class="hljs-title">TodoList</span>, <span class="hljs-title">TodoListId</span>&gt; </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> TodoListId id;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> List&lt;Task&gt; tasks;

    <span class="hljs-meta">@Value(staticConstructor = "of")</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoListId</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Identifier</span> </span>{
        <span class="hljs-meta">@NonNull</span>
        UUID uuid;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> TodoListId <span class="hljs-title">getId</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> id;
    }
    ...
    <span class="hljs-function"><span class="hljs-keyword">public</span> TaskId <span class="hljs-title">addTask</span><span class="hljs-params">(String taskName)</span> </span>{
        <span class="hljs-keyword">if</span> (taskName == <span class="hljs-keyword">null</span> || isWhitespaceName(taskName)) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalTaskName(<span class="hljs-string">"Please specify a non-null, non-whitespace task name!"</span>);
        }
        TaskId taskId = add(TaskId.of(UUID.randomUUID()), taskName, <span class="hljs-keyword">false</span>);
        <span class="hljs-keyword">return</span> taskId;
    }
      ...
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteTask</span><span class="hljs-params">(TaskId task)</span> </span>{
        Optional&lt;Task&gt; foundTask = findTask(task);
        foundTask.ifPresent(tasks::remove);
    }
     ...
}
</code></pre>
<p>What is the <code>AggregateRoot</code> interface good for? Aggregate root is a term from Domain Driven Design (DDD) by Eric Evans:</p>
<blockquote>
<p>An aggregate is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each aggregate has a root and a boundary. The boundary defines what is inside the aggregate. The root is a single, specific entity contained in the aggregate.</p>
</blockquote>
<p>We can change the aggregate’s state only through the aggregate root. In our example that means: we always have to use the <code>TodoList</code> to add, remove, or change a task.</p>
<p>That allows the <code>TodoList</code> to enforce constraints. For example, we can’t add a task with a blank name to the list.</p>
<p>The <code>AggregateRoot</code> interface is part of the <a target="_blank" href="https://github.com/xmolecules/jmolecules">jMolecules</a> library. This library makes DDD concepts explicit in the domain code. During build, <a target="_blank" href="https://github.com/xmolecules/jmolecules-integrations/tree/main/jmolecules-bytebuddy">a ByteBuddy plugin</a> maps the annotations to Spring Data annotations.</p>
<p>So we only have a single model, both for representing domain concepts, and persistence. Still, we don’t have any persistence-specific annotations in the domain code. We don’t tie ourselves to any framework.</p>
<p>The <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/domain/Task.java"><em>Task</em></a> class is similar, but it implements the jMolecules <em>Entity</em> interface instead:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Task</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Entity</span>&lt;<span class="hljs-title">TodoList</span>, <span class="hljs-title">TaskId</span>&gt; </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> TaskId id;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">boolean</span> completed;

    <span class="hljs-meta">@Value(staticConstructor = "of")</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaskId</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Identifier</span> </span>{
        <span class="hljs-meta">@NonNull</span>
        UUID uuid;
    }

    Task(<span class="hljs-meta">@NonNull</span> TaskId id, <span class="hljs-meta">@NonNull</span> String name, <span class="hljs-keyword">boolean</span> completed) {
        <span class="hljs-keyword">this</span>.id = id;
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.completed = completed;
    }
}
</code></pre>
<p>The constructor of <em>Task</em> is package private. So we can’t create an instance of <em>Task</em> from outside of the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/tree/main/samples/todolist/src/main/java/com/example/todolist/domain">domain package</a>. And the <em>Task</em> class is immutable. No changes to its state are possible from outside of the aggregate’s boundary.</p>
<p>We need a repository for storing the <em>TodoList.</em> To stick to domain terms in the domain code, it is called <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/domain/TodoLists.java"><em>TodoLists</em></a>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TodoLists</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Repository</span>&lt;<span class="hljs-title">TodoList</span>, <span class="hljs-title">TodoListId</span>&gt; </span>{
    <span class="hljs-function">TodoList <span class="hljs-title">save</span><span class="hljs-params">(TodoList entity)</span></span>;
    <span class="hljs-function">Optional&lt;TodoList&gt; <span class="hljs-title">findById</span><span class="hljs-params">(TodoListId id)</span></span>;
    <span class="hljs-function">Iterable&lt;TodoList&gt; <span class="hljs-title">findAll</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<p>Again, the code uses a jMolecues annotation: <em>Repository</em>. During build, the ByteBuddy plugin translates it to a Spring Data repository.</p>
<p>We’ll skip the domain exceptions, since there’s nothing special about them. That’s the complete <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/tree/main/samples/todolist/src/main/java/com/example/todolist/domain">domain package</a>.</p>
<h2 id="heading-the-apps-behavior-and-use-cases">The App's Behavior (and Use Cases)</h2>
<p>Next, we define the behavior of the application that is visible to the end user. Any interaction of the user with the application happens as follows:</p>
<ol>
<li>The user interface sends a <em>request</em>.</li>
<li>The backend reacts by executing a <em>request handler.</em> The request handler does everything necessary to fulfill the request:  </li>
<li>Access the database  </li>
<li>Call external services  </li>
<li>Call domain entity methods</li>
<li>The request handler <strong>may</strong> return a <em>response</em>.</li>
</ol>
<p>We implement a <em>request handler</em> with a Java 8 functional interface.</p>
<p>A handler that returns a <em>response</em> implements the <code>java.util.Function</code> interface. Here’s the code of the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/behavior/AddTask.java"><em>AddTask</em></a> handler. This handler</p>
<ul>
<li>extracts the to do list id and task name from an <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/behavior/request/AddTaskRequest.java"><em>AddTaskRequest</em></a><em>,</em></li>
<li>finds the to do list in the repository (or throws an exception),</li>
<li>adds a task with the name from the request to the list,</li>
<li>returns an <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/behavior/response/AddTaskResponse.java"><em>AddTaskResponse</em></a> with the added task’s id.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-meta">@AllArgsConstructor</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AddTask</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Function</span>&lt;<span class="hljs-title">AddTaskRequest</span>, <span class="hljs-title">AddTaskResponse</span>&gt; </span>{
    <span class="hljs-meta">@NonNull</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> TodoLists repository;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> AddTaskResponse <span class="hljs-title">apply</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> AddTaskRequest request)</span> </span>{
        <span class="hljs-keyword">final</span> UUID todoListUuid = request.getTodoListUuid();
        <span class="hljs-keyword">final</span> String taskName = request.getTaskName();

        <span class="hljs-keyword">final</span> TodoList todoList = repository.findById(TodoListId.of(todoListUuid))
            .orElseThrow(() -&gt; <span class="hljs-keyword">new</span> TodoListNotFound(<span class="hljs-string">"Repository doesn't contain a TodoList of id "</span> + todoListUuid));

        TaskId taskId = todoList.addTask(taskName);
        repository.save(todoList);

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> AddTaskResponse(taskId.getUuid());
    }
}
</code></pre>
<p>Lombok creates a constructor with the <em>TodoLists</em> repository interface as constructor argument. We pass in any external dependency as interface to the handler’s constructor.</p>
<p>The requests and responses are immutable objects:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Value</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AddTaskRequest</span> </span>{
    <span class="hljs-meta">@NonNull</span>
    UUID todoListUuid;

    <span class="hljs-meta">@NonNull</span>
    String taskName;
}
</code></pre>
<p>The Modern Clean Architecture libraries (de)serialize them from/to JSON.</p>
<p>Next, an example of a handler that doesn’t return a response. The <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/behavior/DeleteTask.java"><em>DeleteTask</em></a> handler receives a <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/behavior/request/DeleteTaskRequest.java"><em>DeleteTaskRequest</em></a>. Since the handler doesn’t return a response, it implements the <em>Consumer</em> interface.</p>
<pre><code class="lang-java"><span class="hljs-meta">@AllArgsConstructor</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeleteTask</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Consumer</span>&lt;<span class="hljs-title">DeleteTaskRequest</span>&gt; </span>{
    <span class="hljs-meta">@NonNull</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> TodoLists repository;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">accept</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> DeleteTaskRequest request)</span> </span>{
        <span class="hljs-keyword">final</span> UUID todoListUuid = request.getTodoListUuid();
        <span class="hljs-keyword">final</span> UUID taskUuid = request.getTaskUuid();

        <span class="hljs-keyword">final</span> TodoList todoList = repository.findById(TodoListId.of(todoListUuid))
            .orElseThrow(() -&gt; <span class="hljs-keyword">new</span> TodoListNotFound(<span class="hljs-string">"Repository doesn't contain a TodoList of id "</span> + todoListUuid));

        todoList.deleteTask(TaskId.of(taskUuid));
        repository.save(todoList);
    }
}
</code></pre>
<p>One question remains: who creates these handlers?</p>
<p>The answer: a class implementing the <a target="_blank" href="https://github.com/bertilmuth/requirementsascode/blob/master/requirementsascodecore/src/main/java/org/requirementsascode/BehaviorModel.java"><em>BehaviorModel</em></a> interface. The behavior model maps each <em>request</em> class to the <em>request handler</em> for this kind of request.</p>
<p>Here’s a part of the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/behavior/TodoListBehaviorModel.java"><em>TodoListBehaviorModel</em></a>:</p>
<pre><code class="lang-java"><span class="hljs-meta">@AllArgsConstructor</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoListBehaviorModel</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">BehaviorModel</span> </span>{
    <span class="hljs-meta">@NonNull</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> TodoLists todoLists;
    ...
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Model <span class="hljs-title">model</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Model.builder()
            .user(FindOrCreateListRequest.class).systemPublish(findOrCreateList())
            .user(AddTaskRequest.class).systemPublish(addTask())
            .user(ToggleTaskCompletionRequest.class).system(toggleTaskCompletion())
            ...
            .build();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Function&lt;FindOrCreateListRequest, FindOrCreateListResponse&gt; <span class="hljs-title">findOrCreateList</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> FindOrCreateList(todoLists);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Function&lt;AddTaskRequest, AddTaskResponse&gt; <span class="hljs-title">addTask</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> AddTask(todoLists);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Consumer&lt;ToggleTaskCompletionRequest&gt; <span class="hljs-title">toggleTaskCompletion</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ToggleTaskCompletion(todoLists);
    }
    ...
}
</code></pre>
<p>The <code>user(...)</code> statements define the request classes. We use <code>systemPublish(...)</code> for handlers that return a <em>response</em>, and <code>system(...)</code> for handlers that don’t.</p>
<p>The <em>behavior model</em> has a constructor with external dependencies passed in as interfaces. And it creates all handlers and injects the appropriate dependencies into them.</p>
<p>By configuring the dependencies of the <em>behavior model</em>, we configure all handlers. That’s exactly what we want: a central place where we can change or switch the dependencies to technology. That’s how technology decisions can change without affecting the domain code.</p>
<h2 id="heading-the-apps-web-layer-the-adapters">The Apps' Web Layer (the Adapters)</h2>
<p>The web layer in a modern clean architecture can be very thin. In its simplest form, it consists of only 2 classes:</p>
<ul>
<li>One class for configuration of dependencies</li>
<li>One class for exception handling</li>
</ul>
<p>Here’s the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/adapter/spring/TodoListConfiguration.java"><em>TodoListConfiguration</em></a> class:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Configuration</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoListConfiguration</span> </span>{
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function">TodoListBehaviorModel <span class="hljs-title">behaviorModel</span><span class="hljs-params">(TodoLists repository)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> TodoListBehaviorModel(repository);
    }
}
</code></pre>
<p>Spring injects the implementation of the <em>TodoLists</em> repository interface into the <em>behaviorModel(…)</em> method. That method creates a <em>behavior model</em> implementation as a bean.</p>
<p>If the application uses external services, the configuration class is the place to create the concrete instances as beans. And inject them into the <em>behavior model</em>.</p>
<p>So, where are all the controllers?</p>
<p>Well, there aren’t any that you have to create. At least if you only handle POST requests. (For the handling of GET requests, see the Q&amp;A later.)</p>
<p>The <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/tree/main/spring-behavior-web"><em>spring-behavior-web</em></a> library is part of the <em>Modern Clean Architecture</em> libraries. We define a single endpoint for requests. We specify the URL of that endpoint in the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/resources/application.properties"><em>application.properties</em></a>:</p>
<p><code>behavior.endpoint = /todolist</code></p>
<p>If that property exists, spring-behavior-web sets up a controller for the endpoint in the background. That controller receives POST requests.</p>
<p>We don’t need to write Spring specific code to add new behavior. And we don’t need to add or change a controller.</p>
<p>Here’s what happens when the endpoint receives a POST request:</p>
<ol>
<li>spring-behavior-web deserializes the request,</li>
<li>spring-behavior-web passes the request to a behavior configured by the behavior model,</li>
<li>the behavior passes the request to the appropriate request handler (if there is one),</li>
<li>spring-behavior-web serializes the response and passes it back to the endpoint (if there is one).</li>
</ol>
<p>By default, spring-behavior-web wraps every call to a request handler in a transaction.</p>
<h3 id="heading-how-to-send-post-requests">How to send POST requests</h3>
<p>Once we start the Spring Boot application, we can send POST requests to the endpoint.</p>
<p>We include a <code>@type</code> property in the JSON content so that spring-behavior-web can determine the right request class during deserialization.</p>
<p>For example, this is a valid <code>curl</code> command of the To Do List application. It sends a <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/behavior/request/FindOrCreateListRequest.java"><em>FindOrCreateListRequest</em></a> to the endpoint.</p>
<p><code>curl -H "Content-Type: application/json" -X POST -d '{"@type": "FindOrCreateListRequest"}' [http://localhost:8080/todolist](http://localhost:8080/todolist)</code></p>
<p>And that’s the corresponding syntax to use in Windows PowerShell:</p>
<p><code>iwr http://localhost:8080/todolist -Method 'POST' -Headers @{'Content-Type' = 'application/json'} -Body '{"@type": "FindOrCreateListRequest"}'</code></p>
<h3 id="heading-exception-handling">Exception handling</h3>
<p>Exception handling with spring-behavior-web is no different than in “normal” Spring applications. We create a class annotated with <code>@ControllerAdvice</code>. And we place methods annotation with <code>@ExceptionHandler</code> in it.</p>
<p>See the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/adapter/spring/TodoListExceptionHandling.java"><em>TodoListExceptionHandling</em></a> for example:</p>
<pre><code class="lang-java"><span class="hljs-meta">@ControllerAdvice</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoListExceptionHandling</span> </span>{
    <span class="hljs-meta">@ExceptionHandler({ Exception.class })</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ResponseEntity&lt;ExceptionResponse&gt; <span class="hljs-title">handle</span><span class="hljs-params">(Exception e)</span> </span>{
        <span class="hljs-keyword">return</span> responseOf(e, BAD_REQUEST);
    }
    ...
}
</code></pre>
<p>Note that in a real application, the different exception types need different treatment.</p>
<h2 id="heading-the-apps-front-end">The App's Front End</h2>
<p>The front end of the To Do List application consists of:</p>
<ul>
<li>a <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/resources/static/index.html">HTML page</a>,</li>
<li>a <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/resources/static/styles.css">CSS file</a> for formatting,</li>
<li>and a the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/resources/static/main.js">main.js JavaScript file</a></li>
</ul>
<p>We focus on main.js here. It sends requests and updates the web page.</p>
<p>Here’s part of its content:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// URL for posting all requests,</span>
<span class="hljs-comment">// Must be the same as the one in application.properties</span>
<span class="hljs-comment">// (See https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/resources/application.properties)</span>
<span class="hljs-keyword">const</span> BEHAVIOR_ENDPOINT = <span class="hljs-string">"/todolist"</span>;

<span class="hljs-comment">//variables</span>
<span class="hljs-keyword">var</span> todoListUuid;
...

<span class="hljs-comment">// functions</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">restoreList</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-keyword">const</span> request = {<span class="hljs-string">"@type"</span>:<span class="hljs-string">"FindOrCreateListRequest"</span>};

    post(request, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">response</span>)</span>{
        todoListUuid = response.todoListUuid;
        restoreTasksOf(todoListUuid);
    });
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">restoreTasksOf</span>(<span class="hljs-params">todoListUuid</span>) </span>{
    <span class="hljs-keyword">const</span> request = {<span class="hljs-string">"@type"</span>:<span class="hljs-string">"ListTasksRequest"</span>, <span class="hljs-string">"todoListUuid"</span>:todoListUuid};

    post(request, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">response</span>)</span>{    
        showTasks(response.tasks);
    });
}
...
function post(jsonObject, responseHandler) {    
    <span class="hljs-keyword">const</span> xhr = <span class="hljs-keyword">new</span> XMLHttpRequest();
    xhr.open(<span class="hljs-string">"POST"</span>, BEHAVIOR_ENDPOINT);

    xhr.setRequestHeader(<span class="hljs-string">"Accept"</span>, <span class="hljs-string">"application/json"</span>);
    xhr.setRequestHeader(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"application/json"</span>);

    xhr.onreadystatechange = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">if</span> (xhr.readyState === <span class="hljs-number">4</span>) {
            response = xhr.responseText.length &gt; <span class="hljs-number">0</span>? <span class="hljs-built_in">JSON</span>.parse(xhr.response) : <span class="hljs-string">""</span>;
            <span class="hljs-keyword">if</span>(response.error){
                alert(<span class="hljs-string">'Status '</span> + response.status + <span class="hljs-string">' "'</span> + response.message + <span class="hljs-string">'"'</span>);
            } <span class="hljs-keyword">else</span>{
                responseHandler(response);
            }
        }    
    };

    <span class="hljs-keyword">const</span> jsonString = <span class="hljs-built_in">JSON</span>.stringify(jsonObject);
    xhr.send(jsonString);
}
</code></pre>
<p>So for example, this is the JSON object for a <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/blob/main/samples/todolist/src/main/java/com/example/todolist/behavior/request/ListTasksRequest.java"><em>ListTasksRequest</em></a>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> request = {“@type”:”ListTasksRequest”, “todoListUuid”:todoListUuid};
</code></pre>
<p>The <code>post(…)</code> method sends the request to the backend, and passes the response to the response handler (the callback function you passed in as second parameter).</p>
<p>That’s all about the To Do List application.</p>
<h1 id="heading-questions-amp-answers">Questions &amp; Answers</h1>
<p>What if…</p>
<p>… I want to send GET requests instead of POST requests?</p>
<p>… I want the web layer to evolve separately from the behavior?</p>
<p>… I want to use a different framework than Spring?</p>
<p>… I have a much bigger application than the To Do List sample. How do I structure it?</p>
<p><a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/wiki/Questions-&amp;-Answers">Here</a> are the answers.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In this article, I presented you a particular way to implement a Clean Architecture. There are many other ways.</p>
<p>My goal is to reduce the effort of building a Clean Architecture and flatten the learning curve.</p>
<p>To achieve this, the Modern Clean Architecture libraries provide the following features:</p>
<ul>
<li><strong>Serialization of immutable requests and responses</strong> without serialization specific annotations.</li>
<li><strong>No necessity for DTOs.</strong> You can use the same immutable objects for requests/responses in web layer and use cases..</li>
<li><strong>Generic endpoint</strong> that receives and forwards POST requests. New behavior and domain logic can be added and used without the need to write framework specific code.</li>
</ul>
<p>In my next article, I will describe how to test a Modern Clean Architecture.</p>
<p>I invite you to visit the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/">Modern Clean Architecture</a> GitHub page.</p>
<p>See the <a target="_blank" href="https://github.com/bertilmuth/modern-clean-architecture/tree/main/samples/todolist">To Do List sample application</a>.</p>
<p>And please share any feedback you have with me. What do you think about it?</p>
<p>If you want to keep up with what I’m doing or drop me a note, follow me on <a target="_blank" href="https://www.linkedin.com/in/bertilmuth/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/BertilMuth">Twitter</a>.</p>
<h1 id="heading-acknowledgements">Acknowledgements</h1>
<p>Thank you to Surya Shakti for publishing the original front end only <a target="_blank" href="https://suryashakti1999.medium.com/to-do-list-app-using-javascript-for-absolute-beginners-13ea9e38a033">to do list code</a>.</p>
<p>Thank you to Oliver Drotbohm for pointing me to the awesome <a target="_blank" href="https://github.com/xmolecules/jmolecules">jMolecules</a> library.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Simplicity is sophistication ]]>
                </title>
                <description>
                    <![CDATA[ By Srinivasan C Recently I attended a meeting with multiple stakeholders from the business side. When asked to explain a feature, I started explaining them the details of the feature and its implementation. After the meeting one of my colleagues told... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/simplicity/</link>
                <guid isPermaLink="false">66d4614dd14641365a050971</guid>
                
                    <category>
                        <![CDATA[ Clean Architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mental models ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mindset ]]>
                    </category>
                
                    <category>
                        <![CDATA[ soft skill ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 07 Jul 2019 09:54:58 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca1a3740569d1a4ca4fc9.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Srinivasan C</p>
<p>Recently I attended a meeting with multiple stakeholders from the business side. When asked to explain a feature, I started explaining them the details of the feature and its implementation. After the meeting one of my colleagues told me even though I explained it in detail, they will be requesting a follow-up meeting to discuss the same thing and it was true — the next day we had a meeting invite for the same thing as a follow-up. He explained to me that the reason was I had provided them more details than necessary which probably confused them. This incident led me to the principle of Occam’s Razor.</p>
<p>Quoted from Wikipedia</p>
<blockquote>
<p><em>Occam’s razor or the law of parsimony is the problem-solving principle that essentially states that “simpler solutions are more likely to be correct than complex ones.” When presented with competing hypotheses to solve a problem, one should select the solution with the fewest assumptions. The idea is attributed to English Franciscan friar William of Ockham (c. 1287–1347), a scholastic philosopher and theologian.</em></p>
</blockquote>
<p>We have all heard the famous quote by Sherlock Holmes</p>
<blockquote>
<p><em>Once you eliminate the impossible, whatever remains, no matter however improbable, must be the truth.</em></p>
</blockquote>
<p>This follows directly from Occam’s Razor. This principle states that given two explanations of a situation, the one in which there is the least number of variables(simpler) however improbable is the most likely explanation. This principle is very helpful and it can be used in a wide variety of situations but it is especially powerful in the hands of software professional.</p>
<p>There are many areas of Software development which can benefit from this principle. A few of them are:</p>
<h3 id="heading-coding">Coding</h3>
<p>The first and foremost area is coding. As developers, we make hundreds of decisions every day which directly affects the health of the codebase and in turn the business. Few of the mistakes we make include adding unwanted abstractions, designing for the future, making it “extensible”(whatever that means). These code with unwanted additional complexity slowly rots over time and becomes “that” part of the codebase that no one understands and nobody is willing to touch. These are the things we do either knowingly or unknowingly which can put a dent on our codebase health in the long-run.</p>
<p>To overcome this it would be prudent for us to think in terms of Occam’s Razor. Always do the simplest thing possible at any point in time. Principles like YAGNI and KISS are examples of Occam’s Razor in coding. If you want to combine 3 design patterns to accommodate a feature request you expect in the future, restrain your primal instincts and stick with a single class for now. Using Occam’s razor during the development process would keep the codebase simple and readable and your future peers will really thank you.</p>
<p>A word of caution here is, this principle should not be used as an excuse to write bad code or take shortcuts. If there is a real need to add complexity, by all means, you should do that. Consider this a framework for you to step back and think for a moment and weigh the cost of your decision in the long run.</p>
<h3 id="heading-debugging">Debugging</h3>
<p>Another interesting application of this principle is while debugging. The hard part about debugging is nobody knows the answer especially when you work in a legacy code base with business critical functionalities. Bigger the codebase, more complex the debugging process and thus the Occam’s Razor comes in really handy. All the good software developers I know trace the root cause of a bug by using this principle without even realising it.</p>
<p>Let's say there you write a program to display a few stats in the dashboard. You observe that each time the dashboard is updated you get 2x instead of x for a particular stat. What would be your first instinct? Is it a double counting issue or some thread level race condition? I am guessing most of you with go with the former. This is Occam’s Razor in action. You picked the choice which provides the simplest explanation for the issue intuitively.</p>
<p>This is not to say that always the simplest explanation is the right one. Instead, you start from the simplest one and eliminate one by one either by theory or experimentation until you arrive at the actual root cause for the problem. This provides a framework for you to tackle problems methodically.</p>
<h3 id="heading-communication">Communication</h3>
<p>One of the most under-rated functions of a software developer is communication. Be it with peers/ managers/ stakeholders, communication is as important as coding for any developer. As developers, we are the closest to any given problem and it is natural for people to rely on us for understanding the whole picture of a product/feature. This makes what you communicate and how you communicate extremely crucial from a business standpoint.</p>
<p>As we are closest to a problem, we will have a lot of technical and domain knowledge around it. But it is extremely important to communicate the right things to the right people. Assume you are in a mail thread with Sr. engineer, PM, Manager, and a Business development executive, you need to provide just the right amount of detail so that the Engineer can get the technical challenges and the others can also understand the complexity technically as well as the business justification. You need to achieve the right amount of balance in the technical/business mixture for the audience to understand and not lose interest. This is where Occam’s razor comes in. You need to provide the least level of detail in the mail and schedule a follow up for the people who need to understand more.</p>
<p>Take this as an example “we did a POC on x and we were able to achieve y. Even though we discussed A in the previous mail, we could not achieve A due to the complexities in a library that we were using. There were a lot of assumptions in the threading model in the library and thus it prevented us from achieving A”.</p>
<p>Now, what do you think the different stakeholders will understand?</p>
<ol>
<li>Engineer — Yes I get the issue.</li>
<li>PM- So basically we cant achieve A. And what is a threading model?</li>
<li>Manager — Did he try enough to achieve A?</li>
</ol>
<p>Instead, if we write “we did a POC on x and were able to achieve y. A was targetted but not achieved. I’ll schedule a meeting to demo the POC and go into details on the blocker for A.” After that, you have all the time in the world to explain in detail the blockers for the right audience and achieve a consensus.</p>
<p>Now, what is the thought process after the demo?</p>
<ol>
<li>Engineer — Makes sense.</li>
<li>PM — The POC is good for now. I guess we can drop A for now and proceed without it.</li>
<li>Manager — He has done an in-depth analysis and knows what he is doing.</li>
</ol>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Occam’s Razor can be employed in a wide variety of scenarios and these are just a few examples. Developers use this principle intuitively without knowing it. But knowing it and using it deliberately in various situations will greatly improve you as a software developer. If you can think of any other area of Software where this principle is being used feel free to leave your thoughts in comments.</p>
<hr>
<p>If you liked this article, feel free to reach out to me at <a target="_blank" href="https://kaizencoder.com/contact">https://kaizencoder.com/contact</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement a Hexagonal Architecture ]]>
                </title>
                <description>
                    <![CDATA[ By Bertil Muth A hexagonal  architecture simplifies deferring or changing technology decisions. You  want to change to a different framework? Write a new adapter. You want  to use a database, instead of storing data in files? Again, write an  adapter... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/implementing-a-hexagonal-architecture/</link>
                <guid isPermaLink="false">66d45dde55db48792eed3f43</guid>
                
                    <category>
                        <![CDATA[ Clean Architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Hexagonal Architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 19 Jun 2019 21:54:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/aluminum-architecture-art-1492232.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Bertil Muth</p>
<p>A hexagonal  architecture simplifies deferring or changing technology decisions. You  want to change to a different framework? Write a new adapter. You want  to use a database, instead of storing data in files? Again, write an  adapter for it.</p>
<p>Draw a boundary around the business logic. The hexagon. Anything inside the hexagon must be free from technology concerns.<br> The  outside of the hexagon talks with the inside only by using interfaces,  called ports. Same the other way around. By changing the implementation  of a port, you change the technology.</p>
<p>Isolating  business logic inside the hexagon has another benefit. It enables  writing fast, stable tests for the business logic. They do not depend on  web technology to drive them, for example.</p>
<p>Here’s  an example diagram. It shows Spring MVC technology as boxes with dotted  lines, ports and adapters as solid boxes, and the hexagon without its  internals:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/grafik.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>An adapter translates between a specific technology and a technology free port. The <code>PoemController</code> adapter on the left receives requests and sends commands to the <code>IReactToCommands</code> port. The <code>PoemController</code> is a regular Spring MVC Controller. Because it actively uses the port, it's called a driver adapter.</p>
<p><code>IReactToCommands</code> is called a driver port. Its implementation is inside the hexagon. It's not shown on the diagram.</p>
<p>On the right side, the <code>SpringMvcPublisher</code> adapter implements the <code>IWriteLines</code> port. This time, the <em>hexagon</em> calls the adapter through the port. That's why <code>SpringMvcPublisher</code> is called a driven adapter. And <code>IWriteLines</code> is called a driven port.</p>
<p>I show you how to implement that application. We go all the way from a  user story to a domain model inside the hexagon. We start with a simple  version of the application that prints to the console. Then we switch  to Spring Boot and Spring MVC.</p>
<h2 id="heading-from-a-user-story-to-ports-amp-adapters">From a user story to ports &amp; adapters</h2>
<p>The company FooBars.io decides to build a Poetry App. The product owner and the developers agree on the following user story:</p>
<p>As a reader<br>I want to read at least one poem each day<br>So that I thrive as a human being</p>
<p>As acceptance criteria, the team agrees on:</p>
<ul>
<li>When the user asks for a poem in a specific language, the system displays a random poem in that language in the console</li>
<li>It's ok to "simulate" the user at first, i.e. no real user interaction. (This will change in future versions.)</li>
<li>Supported languages: English, German</li>
</ul>
<p>The developers meet and draw the following diagram:</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4a_F9pCz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/02hr6f652yran0dz38h1.PNG" alt="poem-hexagon" width="600" height="400" loading="lazy"></p>
<p>So the <code>SimulatedUser</code> sends commands to the <code>IReactToCommands</code> port. It asks for poems in English and German. Here's the code, it's available on <a target="_blank" href="https://github.com/bertilmuth/poem-hexagon">Github</a>.</p>
<p>_poem/simple/driver_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/simple/driver_adapter/SimulatedUser.java">SimulatedUser.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimulatedUser</span> </span>{
    <span class="hljs-keyword">private</span> IReactToCommands driverPort;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SimulatedUser</span><span class="hljs-params">(IReactToCommands driverPort)</span> </span>{
        <span class="hljs-keyword">this</span>.driverPort = driverPort;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
        driverPort.reactTo(<span class="hljs-keyword">new</span> AskForPoem(<span class="hljs-string">"en"</span>));
        driverPort.reactTo(<span class="hljs-keyword">new</span> AskForPoem(<span class="hljs-string">"de"</span>));
    }
}
</code></pre>
<p>The <code>IReactToCommands</code> port has only one method to receive any kind of command.</p>
<p>_poem/boundary/driver_port/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/driver_port/IReactToCommands.java">IReactToCommands.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IReactToCommands</span></span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">reactTo</span><span class="hljs-params">(Object command)</span></span>;
}
</code></pre>
<p><code>AskForPoem</code> is the command. Instances are simple, immutable POJOs. They carry the language of the requested poem.</p>
<p><em>poem/command/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/command/AskForPoem.java">AskForPoem.java</a></em></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AskForPoem</span> </span>{
    <span class="hljs-keyword">private</span> String language;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AskForPoem</span><span class="hljs-params">(String language)</span> </span>{
        <span class="hljs-keyword">this</span>.language = language;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getLanguage</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> language;
    }
}
</code></pre>
<p>And that's it for the left, driver side of the hexagon. On to the right, driven side.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cMUjGG4H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8vsbpug5fjfjzs8sfs2y.PNG" alt="poem-hexagon: driven side up next" width="600" height="400" loading="lazy"></p>
<p>When the <code>SimulatedUser</code> asks the <code>IReactToCommands</code> port for a poem, the hexagon:</p>
<ol>
<li>Contacts the <code>IObtainPoems</code> port for a collection of poems</li>
<li>Picks a random poem from the collection</li>
<li>Tells the <code>IWriteLines</code> port to write the poem to the output device</li>
</ol>
<p>You can't see Step 2 yet. It happens inside the hexagon, in the  domain model. That's the business logic of the example. So we focus on  Step 1 and Step 3 first.</p>
<p>In Step 1, the collection of poems is a language dependent, hard coded array. It's provided by the <code>HardcodedPoemLibrary</code> adapter that implements the <code>IObtainPoems</code> port.</p>
<p>_poem/boundary/driven_port/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/driven_port/IObtainPoems.java">IObtainPoems.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IObtainPoems</span> </span>{
    String[] getMePoems(String language);
}
</code></pre>
<p>_poem/simple/driven_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/simple/driven_adapter/HardcodedPoemLibrary.java">HardcodedPoemLibrary.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HardcodedPoemLibrary</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IObtainPoems</span> </span>{
    <span class="hljs-keyword">public</span> String[] getMePoems(String language) {
        <span class="hljs-keyword">if</span> (<span class="hljs-string">"de"</span>.equals(language)) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> String[] { <span class="hljs-comment">/* Omitted for brevity */</span> };
        } <span class="hljs-keyword">else</span> { 
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> String[] { <span class="hljs-comment">/* Omitted for brevity */</span> };
        }
    }
}
</code></pre>
<p>In Step 3, the <code>ConsoleWriter</code> adapter writes the lines of the poems to the output device, i.e. the console.</p>
<p>_poem/boundary/driven_port/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/driven_port/IWriteLines.java">IWriteLines.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IWriteLines</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">writeLines</span><span class="hljs-params">(String[] strings)</span></span>;
}
</code></pre>
<p>_poem/simple/driven_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/simple/driven_adapter/ConsoleWriter.java">ConsoleWriter.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConsoleWriter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IWriteLines</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">writeLines</span><span class="hljs-params">(String[] lines)</span> </span>{
        Objects.requireNonNull(lines);
        <span class="hljs-keyword">for</span> (String line : lines) {
            System.out.println(line);
        }
        System.out.println(<span class="hljs-string">""</span>);
    }
}
</code></pre>
<p>We have created all the ports, and a simple implementation of all the  adapters. So far, the inside of the hexagon remained a mystery. It's up  next.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s---tA0dZqp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/efcfrsrwb9jei5uik63k.PNG" alt="poem-hexagon: inside up next" width="600" height="400" loading="lazy"></p>
<h1 id="heading-command-handlers-inside-the-hexagon">Command handlers (inside the hexagon)</h1>
<p>When a user asks for a poem, the system displays a random poem.<br>Similar in the code: when the <code>IReactToCommands</code> port receives an <code>AskForPoem</code>command, the hexagon calls a <code>DisplayRandomPoem</code> command handler.</p>
<p>The <code>DisplayRandomPoem</code> command handler obtains a list of  poems, picks a random one and writes it to the output device. This is  exactly the list of steps we talked about in the last clause.</p>
<p>_poem/boundary/internal/command_handler/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/internal/command_handler/DisplayRandomPoem.java">DisplayRandomPoem.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DisplayRandomPoem</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Consumer</span>&lt;<span class="hljs-title">AskForPoem</span>&gt; </span>{
        <span class="hljs-comment">/* Omitted for brevity */</span>

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">accept</span><span class="hljs-params">(AskForPoem askForPoem)</span> </span>{
        List&lt;Poem&gt; poems = obtainPoems(askForPoem);
        Optional&lt;Poem&gt; poem = pickRandomPoem(poems);
        writeLines(poem);   
    }

        <span class="hljs-comment">/* Rest of class omitted for brevity */</span>
}
</code></pre>
<p>It's also the job of the command handler to translate between the domain model data and the data used in the port interfaces.</p>
<h1 id="heading-tying-commands-to-command-handlers">Tying commands to command handlers</h1>
<p>In my implementation of a hexagonal architecture, there is only a single driver port, <code>IReactToCommands</code>. It reacts to all types of commands.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IReactToCommands</span></span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">reactTo</span><span class="hljs-params">(Object command)</span></span>;
}
</code></pre>
<p>The <code>Boundary</code> class is the implementation of the <code>IReactToCommands</code> port. It creates a behavior model using a <a target="_blank" href="https://github.com/bertilmuth/requirementsascode">library</a>. The behavior model maps each command type to a command handler. Then, a behavior dispatches the commands based on the behavior model.</p>
<p><em>poem/boundary/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/Boundary.java">Boundary.java</a></em></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Boundary</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IReactToCommands</span>, <span class="hljs-title">BehaviorModel</span> </span>{
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> IObtainPoems poemObtainer;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> IWriteLines lineWriter;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> StatelessBehavior behavior;

  <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Class&lt;AskForPoem&gt; asksForPoem = AskForPoem.class;

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Boundary</span><span class="hljs-params">(IObtainPoems poemObtainer, IWriteLines lineWriter)</span> </span>{
    <span class="hljs-keyword">this</span>.poemObtainer = poemObtainer;
    <span class="hljs-keyword">this</span>.lineWriter = lineWriter;
    <span class="hljs-keyword">this</span>.behavior = StatelessBehavior.of(<span class="hljs-keyword">this</span>);
  }

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> Model <span class="hljs-title">model</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> Model.builder()
        .user(asksForPoem).system(displaysRandomPoem())
        .build();
  }

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">reactTo</span><span class="hljs-params">(Object commandObject)</span> </span>{
    behavior.reactTo(commandObject);
  }

  <span class="hljs-function"><span class="hljs-keyword">private</span> Consumer&lt;AskForPoem&gt; <span class="hljs-title">displaysRandomPoem</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> DisplayRandomPoem(poemObtainer, lineWriter);
  }
}
</code></pre>
<h1 id="heading-the-domain-model">The domain model</h1>
<p>The domain model of the example doesn’t have very interesting functionality. The <a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/internal/domain/RandomPoemPicker.java">RandomPoemPicker</a> picks a random poem from a list.</p>
<p>A <a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/internal/domain/Poem.java">Poem</a> has a constructor that takes a String containing line separators, and splits it into verses.</p>
<p>The really interesting bit about the example domain model: it doesn’t  refer to a database or any other technology, not even by interface!</p>
<p>That means that you can test the domain model with <a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/test/java/poem/boundary/internal/domain/RandomPoemPickerTest.java">plain unit tests</a>. You don’t need to mock anything.</p>
<p>Such a pure domain model is not a necessary property of an  application implementing a hexagonal architecture. But I like the  decoupling and testability it provides.</p>
<h1 id="heading-plug-adapters-into-ports-and-thats-it">Plug adapters into ports, and that's it</h1>
<p>A final step remains to make the application work. The application  needs a main class that creates the driven adapters. It injects them  into the boundary.<br>It then creates the driver adapter,  for the boundary, and runs it.</p>
<p><em>poem/simple/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/simple/Main.java">Main.java</a></em></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">new</span> Main().startApplication();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startApplication</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Instantiate driven, right-side adapters</span>
        HardcodedPoemLibrary poemLibrary = <span class="hljs-keyword">new</span> HardcodedPoemLibrary();
        ConsoleWriter consoleWriter = <span class="hljs-keyword">new</span> ConsoleWriter();

        <span class="hljs-comment">// Inject driven adapters into boundary</span>
        Boundary boundary = <span class="hljs-keyword">new</span> Boundary(poemLibrary, consoleWriter);

        <span class="hljs-comment">// Start the driver adapter for the application</span>
        <span class="hljs-keyword">new</span> SimulatedUser(boundary).run();
    }
}
</code></pre>
<p>And that's it! The team shows the result to the product owner. And  she's happy with the progress. Time for a little celebration.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PDHorQ0r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6pe5yam3xe68m11bojff.PNG" alt="hexagon-poem the completed application" width="600" height="400" loading="lazy"></p>
<h1 id="heading-switching-to-spring">Switching to Spring</h1>
<p>The team decides to turn the poem app into a web application. And to  store poems in a real database. They agree to use the Spring framework  to implement it.<br>Before they start coding, the team meets and draws the following diagram:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/grafik-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Instead of a <code>SimulatedUser</code>, there is a <code>PoemController</code> now, that sends commands to the hexagon.</p>
<p>_poem/springboot/driver_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/driver_adapter/PoemController.java">PoemController.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-meta">@Controller</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PoemController</span> </span>{
    <span class="hljs-keyword">private</span> SpringMvcBoundary springMvcBoundary;

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PoemController</span><span class="hljs-params">(SpringMvcBoundary springMvcBoundary)</span> </span>{
        <span class="hljs-keyword">this</span>.springMvcBoundary = springMvcBoundary;
    }

    <span class="hljs-meta">@GetMapping("/askForPoem")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">askForPoem</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(name = "lang", required = false, defaultValue = "en")</span> String language,
            Model webModel)</span> </span>{
        springMvcBoundary.basedOn(webModel).reactTo(<span class="hljs-keyword">new</span> AskForPoem(language));

        <span class="hljs-keyword">return</span> <span class="hljs-string">"poemView"</span>;
    }
}
</code></pre>
<p>When receiving a command, the <code>PoemController</code> calls <code>springMvcBoundary.basedOn(webModel)</code>. This creates a new <code>Boundary</code> instance, based on the <code>webModel</code> of the request:</p>
<p><em>poem/springboot/boundary/<a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/boundary/SpringMvcBoundary.java">SpringMvcBoundary.java</a></em></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SpringMvcBoundary</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> IObtainPoems poemObtainer;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SpringMvcBoundary</span><span class="hljs-params">(IObtainPoems poemObtainer)</span> </span>{
        <span class="hljs-keyword">this</span>.poemObtainer = poemObtainer;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> IReactToCommands <span class="hljs-title">basedOn</span><span class="hljs-params">(Model webModel)</span> </span>{
        SpringMvcPublisher webPublisher = <span class="hljs-keyword">new</span> SpringMvcPublisher(webModel);
        IReactToCommands boundary = <span class="hljs-keyword">new</span> Boundary(poemObtainer, webPublisher);
        <span class="hljs-keyword">return</span> boundary;
    }
}
</code></pre>
<p>The call to <code>reactTo()</code> sends the command to the boundary, as before. On the right side of the hexagon, the <code>SpringMvcPublisher</code> adds an attribute <code>lines</code> to the Spring MVC model. That's the value Thymeleaf uses to insert the lines into the web page.</p>
<p>_poem/springboot/driven_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/driven_adapter/SpringMvcPublisher.java">SpringMvcPublisher.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SpringMvcPublisher</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IWriteLines</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String LINES_ATTRIBUTE = <span class="hljs-string">"lines"</span>;

    <span class="hljs-keyword">private</span> Model webModel;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SpringMvcPublisher</span><span class="hljs-params">(Model webModel)</span> </span>{
        <span class="hljs-keyword">this</span>.webModel = webModel;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">writeLines</span><span class="hljs-params">(String[] lines)</span> </span>{
        Objects.requireNonNull(lines);
        webModel.addAttribute(LINES_ATTRIBUTE, lines);
    }
}
</code></pre>
<p>The team also implements a <code>PoemRepositoryAdapter</code> to access the <code>PoemRepository</code>. The adapter gets the <code>Poem</code> objects from the database. It returns the texts of all poems as a String array.</p>
<p>_poem/springboot/driven_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/driven_adapter/PoemRepositoryAdapter.java">PoemRepositoryAdapter.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PoemRepositoryAdapter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IObtainPoems</span> </span>{
    <span class="hljs-keyword">private</span> PoemRepository poemRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PoemRepositoryAdapter</span><span class="hljs-params">(PoemRepository poemRepository)</span> </span>{
        <span class="hljs-keyword">this</span>.poemRepository = poemRepository;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-keyword">public</span> String[] getMePoems(String language) {
        Collection&lt;Poem&gt; poems = poemRepository.findByLanguage(language);
        <span class="hljs-keyword">final</span> String[] poemsArray = poems.stream()
            .map(p -&gt; p.getText())
            .collect(Collectors.toList())
            .toArray(<span class="hljs-keyword">new</span> String[<span class="hljs-number">0</span>]);
        <span class="hljs-keyword">return</span> poemsArray;
    }
}
</code></pre>
<p>Finally, the team implements the <a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/Application.java">Application</a> class that sets up an example repository and plugs the adapters into the ports.</p>
<p>And that's it. The switch to Spring is complete.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>There are many ways to implement a hexagonal architecture. I showed  you a straightforward approach that provides an easy to use, command  driven API for the hexagon. It reduces the number of interfaces you need  to implement. And it leads to a pure domain model.</p>
<p>If you want to get more information on the topic, read <a target="_blank" href="http://archive.is/5j2NI">Alistair Cockburn’s original article on the subject</a>.</p>
<p>The example in this article is inspired by a three part series of <a target="_blank" href="https://www.youtube.com/playlist?list=PLGl1Jc8ErU1w27y8-7Gdcloy1tHO7NriL">talks</a> by Alistair Cockburn on the subject.</p>
<p><em>Last updated on 30 July 2021.__. If you want to keep up with what I’m doing or drop me a note, follow me on</em> <a target="_blank" href="https://dev.to/bertilmuth"><em>dev.to</em></a><em>,</em> <a target="_blank" href="https://www.linkedin.com/in/bertilmuth/"><em>LinkedIn</em></a> <em>or</em> <a target="_blank" href="https://twitter.com/BertilMuth"><em>Twitter</em></a><em>. Or visit my</em> <a target="_blank" href="https://github.com/bertilmuth/requirementsascode"><em>GitHub project</em></a><em>. To learn about agile software development,</em> <a target="_blank" href="https://skl.sh/2Cq497P"><em>visit my online course</em></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A TypeScript Stab at Clean Architecture ]]>
                </title>
                <description>
                    <![CDATA[ By Warren Bell #  Clean Architecture There are many videos and articles explaining clean architecture. Most of these go over the concepts from a 20,000 foot view. I don’t know about you, but I don’t learn things very well at that elevation. Not a lot... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-typescript-stab-at-clean-architecture-b51fbb16a304/</link>
                <guid isPermaLink="false">66c3436693db2451bd4413f1</guid>
                
                    <category>
                        <![CDATA[ Clean Architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 26 Jul 2018 20:56:12 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*zizBT5zxwmm5mibeF55bow.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Warren Bell</p>
<p># </p>
<h3 id="heading-clean-architecture">Clean Architecture</h3>
<p>There are many videos and articles explaining clean architecture. Most of these go over the concepts from a 20,000 foot view. I don’t know about you, but I don’t learn things very well at that elevation. Not a lot of oxygen up there. I learn by jumping in head first and coding. This article and the accompanying code is what I ended up with after such a leap.</p>
<h3 id="heading-bobs-your-uncle">Bob’s Your Uncle</h3>
<p>The term “Clean Architecture” was made popular by Robert Martin (Uncle Bob) and his book “Clean Architecture: A Craftsman’s Guide to Software Structure and Design.” Now I don’t proclaim to be an expert in this field and I haven’t read his book, though I intend to. But I can completely relate to the problems it is trying to solve.</p>
<p>How do you write a software system that is not dependent on anything other than a primary language ? We were promised this in the past with interfaces and other OO principles, but I had never before seen a “clean”, pun intended, explanation on how to do this regarding the whole system. And yes, I am a bit late to this party, being that Uncle Bob started to talk about these concepts in 2012, which is a century ago in software years.</p>
<h3 id="heading-the-diagram-that-baffled-me">The Diagram That Baffled Me</h3>
<p>Here is the original diagram Uncle Bob and others used in their presentations when explaining Clean Architecture. This simple little diagram became an obsession of mine. I had long ago purged my memory of anything UML related and was struggling with the has-a, and uses-a relationships indicated by the open and close arrow heads. The only way I was going to figure this out was by writing some code.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*Amv74nfUdirQYlRmSyEMDA.png" alt="Image" width="800" height="411" loading="lazy">
<em>Image Credit: Uncle Bob</em></p>
<h3 id="heading-know-your-onions">Know Your Onions</h3>
<p>One way to look at Clean Architecture is as an onion with layers. All layers can only depend on a layer that is closer to the center. That is, all dependencies point inward and not outward.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*nEATDe5dRLIWN3MSxSjG0A.png" alt="Image" width="800" height="576" loading="lazy">
_[Image Credit](https://android.jlelse.eu/thoughts-on-clean-architecture-b8449d9d02df" rel="noopener" target="<em>blank" title=")</em></p>
<h3 id="heading-one-of-these-days-im-gonna-get-organizized">One of These Days, I’m Gonna Get Organizized</h3>
<p>In our example, there are 4 modules that correspond with each layer of this onion. Eventually these could be separate npm modules. For readability’s sake, I tried to name things according to Uncle Bob’s original Clean Architecture diagram at the top of this article. In the real world you would probably preface all names with what ever use case they represented.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*xfnLsbxyTy4s-AEQY7vi2A.png" alt="Image" width="800" height="324" loading="lazy">
<em>Image Credit: Myself</em></p>
<p>The infrastructure (blue) layer is where all of our outside pluggable systems live. These outside systems such as devices, web, and UIs, shown in the onion diagram, will use our IRequest and IViewModel interfaces to communicate with our Controller and Presenter while the db and external interfaces, shown in the onion diagram, will use the IEntityGateway interface to communicate with our Interactor.</p>
<p>Our example will have one entity called a Widget with three properties. It also uses one use case “create widget” which takes a widget from the UI, saves the widget to some sort of storage, and returns back to the UI a newly created widget with an id and a revision number.</p>
<h3 id="heading-more-visual-aids">More Visual Aids</h3>
<p>Here is the directory structure. Everything gets wired together in each module’s index.ts file. The entry point is demonstrated in a test located in infrastructure/test/TestEntryPoint.spec.ts .</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*LRbWuQzcmLh9LOJL5P2HYA.png" alt="Image" width="322" height="927" loading="lazy">
<em>Image Credit: Shift Command 4</em></p>
<h3 id="heading-which-way-did-he-go">Which Way Did He Go?</h3>
<p>One of my original hangups was how the outer most layer communicates with the inner layers. I thought all you had to do is call some createWidget() function, for example, on a Controller and you would get a nice shiny new widget returned back to you. Wrong.</p>
<p>What you want to do is send the widget to be created down to the use case (Interactor) on a certain path and have the use case (Interactor) send the new widget back up to you on a different path. This is similar to a callback function or a Promise. I found a good diagram illustrating this in an article titled “Implementing Clean Architecture — Of controllers and presenters” (link below). In our example I have not implemented a RequestModel or a ResponseModel.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*KMgKFitjUr7K0MaNxuLZGA.png" alt="Image" width="742" height="531" loading="lazy">
_[Image Credit](https://plainionist.github.io/Implementing-Clean-Architecture-Controller-Presenter/" rel="noopener" target="<em>blank" title=")</em></p>
<h3 id="heading-step-into-step-over-and-step-out-the-oo-way">Step Into, Step Over, and Step Out, the OO Way</h3>
<p>So let’s first create a widget with classes and interfaces.</p>
<h3 id="heading-oo-step-1">OO Step 1</h3>
<p>This is the entry point. This code would be located in the infrastructure (blue) layer. This layer is where your mobile app, web app, API, CLI, etc. lives. Also all of your outside systems like external APIs, frameworks, libraries and databases live here too. Everything is pluggable in this layer and communicates with our system via interfaces we provide.</p>
<p>First you create your ViewModel implementation of the IViewModel interface where a new widget will appear and you can update your UI within the implemented function presentWidget(widget).</p>
<p>You then create a Controller that implements the IRequest interface by passing the EntityGateway and the ViewModel you created above to a constructor. Finally your UI calls createWidget(widget) on the Controller where your new widget begins its journey to the Interactor.</p>
<h4 id="heading-whats-an-entitygateway">What’s an EntityGateway?</h4>
<p>An EntityGateway implements the IEntityGateway interface and is where you implement specific code that persists your widget. It lives in the infrastructure (blue) layer. This could be any type of existing or future external API or persistence system such as a database.</p>
<p>To change out to a different system, you would just simply wire together the new EntityGateway implementation with the IEntityGateway interface. In this example, I use a Promise to simulate some sort of persistence operation.</p>
<h4 id="heading-wire-up-what">Wire up What?</h4>
<p>The file infrastructure/src/index.ts in the infrastructure module is where you can wire up your different implementations of your IEntityGateway interface. The “from” path of the import statement points to the correct implementation. In this case it is a persistence system named AnyDB.</p>
<p>Uncle Bob also talks about the use of a Main class where you can do this type of wiring up or do other initializing code. The Main class would also live in the infrastructure module and be pluggable. It would also communicate in the same manner as the other systems in the infrastructure module do. For example, you would initiate this class in your UI’s initializing code and pass it down into your more inner layers to be used via some sort of configuration interface.</p>
<p>Our example does not use a Main class and instead is passing the persistence system down into the interactor via the createWidget() function. This is probably not the “pure” way of doing this, but was done to make our example easier to read.</p>
<h3 id="heading-oo-step-2">OO Step 2</h3>
<p>The Controller is a very busy place. First, the EntityGateway passes through unchanged to our Interactor constructor. Then our ViewModel gets passed to the constructor of our Presenter which in turn also gets passed to our Interactor constructor. This all happens in the createWidget(widget) function of the Controller which was called by our UI in step 1 via the IRequest interface. We will talk about our Presenter in step 4 when the newly created widget travels back up to the UI.</p>
<h3 id="heading-oo-step-3">OO Step 3</h3>
<p>Finally we are at the most inner layer of our journey, the usecase layer where our Interactor lives. Or better known as our home for all of our app’s use case logic. There is one more inner layer, the domain. This is where all of our business entities and business specific logic lives. In this example, we really don’t have any need to go there except to borrow the WidgetType and IEntityGateway interfaces.</p>
<h4 id="heading-movin-on-up">Movin On Up</h4>
<p>Here in our Interactor we take the EntityGateway that was passed through from the Controller and call its saveWidget(widget) function via the IEntityGateway interface. This function returns a Promise from the EntityGateway which resolves in .then() with a newly created widget. We then call the Presenter’s presentWidget(widget) function via the IOutputBoundary interface which starts the newly created widget back up to the UI. This all happens in the Interactor’s createWidget(widget) function which was called by our Controller via the IInputBoundary interface in step 2.</p>
<h3 id="heading-oo-step-4">OO Step 4</h3>
<p>Here in our Presenter, we simply pass the widget to our ViewModel’s presentWidget(widget) function we created in our UI. This all happens in the Presenter’s presentWidget(widget) function via the IOutputBoundary interface which was called in the Interactor’s createWidget(widget) function in step 3. More can happen here, but not in our example.</p>
<h3 id="heading-oo-step-5">OO Step 5</h3>
<p>Finally our newly created widget is back home ready to be displayed in our UI. This is the exact spot (code) where we started in step 1. Updating the UI happens in the ViewModel’s presentWidget(widget) function via the IViewModel interface which was called in the Presenter’s presentWidget(widget) function in step 4.</p>
<h4 id="heading-oo-supporting-cast-members">OO Supporting Cast Members</h4>
<p>Here are all the remaining interfaces and type definitions clumped together in one file.</p>
<h4 id="heading-2-men-enter-1-man-leaves">2 Men Enter 1 Man Leaves</h4>
<p>I wrote the class and interface version of this project first. I wanted to try and make it match Uncle Bob’s original diagram as close as I could. When I finished that project, I realized I could have done the same thing with functions and type definitions. So I created an identical project and replaced Classes with Functions and Interfaces with Type definitions.</p>
<p>And here is the difference between a Controller class and a Controller function.</p>
<h3 id="heading-step-into-step-over-and-step-out-the-function-way">Step Into, Step Over, and Step Out, the Function Way</h3>
<p>Now lets give a stab at creating widgets with functions and type definitions.</p>
<h4 id="heading-general-differences">General Differences</h4>
<p>WidgetType is identical as the OO version above and IEntityGateway, IRequest, IViewModel, IInputBoundary, and IOutputBoundary are now type definitions instead of interfaces.</p>
<h3 id="heading-function-step-1">Function Step 1</h3>
<p>Every thing is the same as OO step 1 above, other than that we are now importing a function named “controllerConstructor” instead of a class named “Controller.” And importing a function named “entityGateway” instead of a class named EntityGateway. Last but not least, the ViewModel we created is now an object with a presentWidget() function in it instead of a class with a presentWidget() function.</p>
<h4 id="heading-entitygateway-again">EntityGateway Again?</h4>
<p>The EntityGateway does the same task as the OO version above. It is now a function instead of a class. It returns a saveWidget() function wrapped in an object.</p>
<h4 id="heading-more-wiring">More Wiring</h4>
<p>Same as OO version above except we are now exporting a function instead of a class.</p>
<h3 id="heading-function-step-2">Function Step 2</h3>
<p>Our Controller is still a busy place and does the same tasks as the OO version. We are now importing a function named interactorConstructor instead of a class named Interactor. We are exporting a function named “controllerConstructor” instead of a class named “Controller.” It returns a function named “createWidget wrapped in an object.</p>
<h3 id="heading-function-step-3">Function Step 3</h3>
<p>Back in the Iteractor in our usecase module, we are executing the same tasks as the OO version above. We are now exporting a function named “interactorConstructor” instead of a class named “Interactor.” It returns a function named “createWidget wrapped in an object.</p>
<h3 id="heading-function-step-4">Function Step 4</h3>
<p>We are now passing the newly created widget back up in our Presenter where we are executing the same tasks as the OO version above. We export a function named “presenterConstructor” instead of a class named “Presenter.” It returns a function named “presentWidget wrapped in an object.</p>
<h3 id="heading-function-step-5">Function Step 5</h3>
<p>Again we have come full circle and we are back in the exact spot (code) where we started in step 1. Our UI gets updated with our newly created widget in the ViewModel’s presentWidget() function.</p>
<h4 id="heading-function-supporting-cast-members">Function Supporting Cast Members</h4>
<p>Here are all the remaining type definitions clumped together in one file. These are our interfaces.</p>
<h3 id="heading-all-that-for-a-damn-widget">All That for a Damn Widget?</h3>
<p>Yes, but you also get the promise of a completely decoupled system where you can plug in different implementations of your outside (infrastructure blue layer) systems, including different types of UIs, external APIs, databases, libraries, frameworks and more.</p>
<h3 id="heading-we-dont-need-no-stinkin-profilers">We Don’t Need No Stinkin Profilers</h3>
<p>My original hunch was that the class and interface version would be slower than the function version. So I ran both projects through my advance profiling tools of typing “npm test” and pressing enter until my finger cramped up.</p>
<p>My first observation was that the function version was about twice as fast, WOW. Then I decided to refactor the function version to return all of the important functions wrapped in objects so I could enforce the function names. I then ran both versions through my advance profilers and they were about the same speed.</p>
<p>I have no idea why wrapping a function in an object would slow it down that much. Maybe I didn’t actually get Adobe Flash completely uninstalled from my laptop and it decided to interfere. Anyways, it would be interesting to get a more accurate measure of speed using the correct tools against the compiled JavaScript.</p>
<h3 id="heading-the-take-away">The Take Away</h3>
<p>The OO version has more code but may be easier to read and follow. The function version has less code but may be harder to read and follow.</p>
<p>Personally I like the function version, being that I have done a lot of programming in Java and I am tired of writing so many classes. One of the things I like the most about TypeScript/JavaScript is the ability to use object literals. And with TypeScript type definitions, you can now apply some safety to using object literals.</p>
<p>Another take away is that you don’t need to rigidly conform to the clean architecture as diagrammed above to achieve a decoupled system. For example, you could just as easily have your UI communicate directly with your use case layer bypassing the delivery layer if it’s not needed. All of these layers may physically live in different places and have different ways of communicating with each other.</p>
<h3 id="heading-give-it-a-try">Give it a Try</h3>
<p>Here are some of the things I intend to enforce in my next project.</p>
<ol>
<li>Dependencies should always go one way.</li>
<li>Dependencies should always point from your outside systems (UI, db, etc.) to your business entities and business logic.</li>
<li>Your inner layers (delivery, use case, and business entities) need to expose interfaces for the more outer layers to use.</li>
<li>You should always start developing from the most inner layer out. Start with the business entities and logic first and test. Create the interfaces that will be used and then test these interfaces. I am guilty of working the other way around. I think we all like to start with the UI, because it immediately lets us visually see how our system will look to a user. Plus the UI is where a lot of the “cool” technologies live.</li>
<li>Use TDD (Test Driven Development). Clean architecture allows you to do this much more easily. Everything is more compartmentalized and easier to mock. The implementation of the IEntityGateway above is basically a mock of a database.</li>
<li>Last but not least, be flexible. Don’t knock yourself out trying to adhere to clean architecture when that library or framework you want to use just won’t work with it. But be warned that this is probably a good indication that you will eventually have some sort of problems regarding that library or framework, especially if it wants you to extend their classes. Decoupling should be your goal.</li>
</ol>
<h3 id="heading-but-but-what-about">But, But, What About…</h3>
<p>Please ask questions and give feedback, there is no better way to learn than to get constructive criticism from your peers. And it is highly probable that I missed something somewhere.</p>
<h3 id="heading-resources">Resources:</h3>
<h4 id="heading-code-for-the-oo-version-is-located-at">Code for the OO version is located at:</h4>
<p><a target="_blank" href="https://github.com/warrenbell/cleanarch-tsoo">https://github.com/warrenbell/cleanarch-tsoo</a></p>
<h4 id="heading-code-for-the-function-version-is-located-at">Code for the function version is located at:</h4>
<p><a target="_blank" href="https://github.com/warrenbell/cleanarch-tsoo">https://github.com/warrenbell/cleanarch-ts</a>fun</p>
<h4 id="heading-ts-node">ts-node</h4>
<p>Handy little TypeScript tool.</p>
<p><a target="_blank" href="https://github.com/TypeStrong/ts-node">https://github.com/TypeStrong/ts-node</a></p>
<h4 id="heading-the-clean-architecture-by-uncle-bob">The Clean Architecture by Uncle Bob</h4>
<p><a target="_blank" href="https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html">https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html</a></p>
<h4 id="heading-the-book">The Book</h4>
<p><a target="_blank" href="https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164">https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164</a></p>
<h4 id="heading-one-of-many-videos">One of Many Videos</h4>
<p>They are all basically the same except for the the first 5 minutes where Uncle Bob likes to muse about something loosely related and then makes a hard segue into clean architecture.</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=Nltqi7ODZTM">https://www.youtube.com/watch?v=Nltqi7ODZTM</a></p>
<h4 id="heading-implementing-clean-architecture-of-controllers-and-presenters">Implementing Clean Architecture — Of controllers and presenters</h4>
<p><a target="_blank" href="https://plainionist.github.io/Implementing-Clean-Architecture-Controller-Presenter/">https://plainionist.github.io/Implementing-Clean-Architecture-Controller-Presenter/</a></p>
<h4 id="heading-clean-architecture-standing-on-the-shoulders-of-giants">Clean Architecture: Standing on the shoulders of giants</h4>
<p><a target="_blank" href="https://herbertograca.com/2017/09/28/clean-architecture-standing-on-the-shoulders-of-giants/">https://herbertograca.com/2017/09/28/clean-architecture-standing-on-the-shoulders-of-giants/</a></p>
<h4 id="heading-clean-architecture-use-case-containing-the-presenter-or-returning-data">Clean Architecture: Use case containing the presenter or returning data?</h4>
<p><a target="_blank" href="https://softwareengineering.stackexchange.com/questions/357052/clean-architecture-use-case-containing-the-presenter-or-returning-data">https://softwareengineering.stackexchange.com/questions/357052/clean-architecture-use-case-containing-the-presenter-or-returning-data</a></p>
<h4 id="heading-clean-architecture-what-are-the-jobs-of-presenter">Clean architecture. What are the jobs of presenter?</h4>
<p><a target="_blank" href="https://stackoverflow.com/questions/46510550/clean-architecture-what-are-the-jobs-of-presenter">https://stackoverflow.com/questions/46510550/clean-architecture-what-are-the-jobs-of-presenter</a></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
