{"id":1846,"date":"2016-11-24T18:22:07","date_gmt":"2016-11-24T17:22:07","guid":{"rendered":"https:\/\/www.entropywins.wtf\/blog\/?p=1846"},"modified":"2019-02-23T06:11:21","modified_gmt":"2019-02-23T05:11:21","slug":"implementing-the-clean-architecture","status":"publish","type":"post","link":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/","title":{"rendered":"Implementing the Clean Architecture"},"content":{"rendered":"<p>Both Domain Driven Design and architectures such as the Clean Architecture and Hexagonal are often talked about. It&#8217;s hard to go to a conference on software development and not run into one of these topics. However it can be challenging to find good real-world examples. In this blog post I&#8217;ll introduce you to an application following the Clean Architecture and incorporating a lot of DDD patterns. The focus is on the key concepts of the Clean Architecture, and the most important lessons we learned implementing it.<\/p>\n<h3>The application<\/h3>\n<p>The real-world application we&#8217;ll be looking at is the Wikimedia Deutschland fundraising software. It is a PHP application written in 2016, replacing an older legacy system. While the application is written in PHP, the patterns followed are by and large language agnostic, and are thus relevant for anyone writing object orientated software.<\/p>\n<p>I&#8217;ve outlined what the application is and why we replaced the legacy system in a blog post titled <a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/rewriting-the-wikimedia-deutschland-funrdraising\/\">Rewriting the Wikimedia Deutschland fundraising<\/a>. I recommend you have a look at least at its &#8220;The application&#8221; section, as it will give you a rough idea of the domain we&#8217;re dealing with.<\/p>\n<h3>A family of architectures<\/h3>\n<p>Architectures such as Hexagonal and the Clean Architecture are very similar. At their core, they are about separation of concerns. They decouple from mechanisms such as persistence and used frameworks and instead focus on the domain and high level policies. A nice short read on this topic is Unclebob&#8217;s <a href=\"https:\/\/8thlight.com\/blog\/uncle-bob\/2012\/08\/13\/the-clean-architecture.html\">blog post on the Clean Architecture<\/a>. Another recommended post is <a href=\"http:\/\/tpierrain.blogspot.de\/2016\/04\/hexagonal-layers.html\"> Hexagonal != Layers<\/a>, which explains that how just creating a bunch of layers is missing the point.<\/p>\n<h3>The Clean Architecture<\/h3>\n<p><a href=\"https:\/\/8thlight.com\/blog\/uncle-bob\/2012\/08\/13\/the-clean-architecture.html\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1863\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/cleanarchitecture\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\" data-orig-size=\"772,567\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;1&quot;}\" data-image-title=\"cleanarchitecture\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\" class=\"alignnone size-full wp-image-1863\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\" alt=\"cleanarchitecture\" width=\"772\" height=\"567\" \/><\/a><\/p>\n<p>The arrows crossing the circle boundaries represent the allowed direction of dependencies. At the core is the domain. &#8220;Entities&#8221; here means Entities such as in Domain Driven Design, not to be confused by ORM entities. The domain is surrounded by a layer containing use cases (sometimes called interactors) that form an API that the outside world, such as a controller, can use to interact with the domain. The use cases themselves only bind to the domain and certain cross cutting concerns such as logging, and are devoid of binding to the web, the database and the framework.<\/p>\n<pre class=\"lang:php decode:true \">class CancelDonationUseCase {\n    private \/* DonationRepository *\/ $repository;\n    private \/* Mailer *\/ $mailer;\n\n    public function cancelDonation( CancelDonationRequest $r ): CancelDonationResponse {\n        $this-&gt;validateRequest( $r );\n\n        $donation = $this-&gt;repository-&gt;getDonationById( $r-&gt;getDonationId() );\n        $donation-&gt;cancel();\n        $this-&gt;repository-&gt;storeDonation( $donation );\n\n        $this-&gt;sendConfirmationEmail( $donation );\n\n        return new CancelDonationResponse( \/* ... *\/ );\n    }\n}\n<\/pre>\n<p>In this example you can see how the UC for canceling a donation gets a request object, does some stuff, and then returns a response object. Both the request and response objects are specific to this UC and lack both domain and presentation mechanism binding. The stuff that is actually done is mainly interaction with the domain through Entities, Aggregates and Repositories.<\/p>\n<pre class=\"lang:php decode:true \">$app-&gt;post(\n    '\/cancel-donation',\n    function( Request $httpRequest ) use ( $factory ) {\n        $requestModel = new CancelDonationRequest(\n            $httpRequest-&gt;request-&gt;get( 'donation_id' ),\n            $httpRequest-&gt;request-&gt;get( 'update_token' )\n        );\n\n        $useCase = $factory-&gt;newCancelDonationUseCase();\n        $responseModel = $useCase-&gt;cancelDonation( $requestModel );\n\n        $presenter = $factory-&gt;newNukeLaunchingResultPresenter();\n        return new Response( $presenter-&gt;present( $responseModel ) );\n    }\n);\n<\/pre>\n<p>This is a typical way of invoking a UC. The framework we&#8217;re using is Silex, which calls the function we provided when the route matches. Inside this function we construct our framework agnostic request model and invoke the UC with it. Then we hand over the response model to a presenter to create the appropriate HTML or other such format. This is all the framework bound code we have for canceling donations. Even the presenter does not bind to the framework, though it does depend on Twig.<\/p>\n<p>If you are familiar with Silex, you might already have noticed that we&#8217;re constructing our UC different than you might expect. We decided to go with our own top level factory, rather than using the dependency injection mechanism provided by Silex: Pimple. Our factory internally actually uses Pimple, though this is not visible from the outside. With this approach we gain a nicer access to service construction, since we can have a <code>getLogger()<\/code> method with <code>LoggerInterface<\/code> return type hint, rather than accessing <code>$app['logger']<\/code> or some such, which forces us to bind to a string and leaves us without type hint.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1864\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/use-case-list\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/use-case-list.jpg\" data-orig-size=\"337,522\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"use-case-list\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/use-case-list.jpg\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/use-case-list.jpg\" class=\"alignnone size-full wp-image-1864\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/use-case-list.jpg\" alt=\"use-case-list\" width=\"337\" height=\"522\" \/><\/p>\n<p>This use case based approach makes it very easy to see what our system is capable off at a glance.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1865\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/use-case-directory\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/use-case-directory.jpg\" data-orig-size=\"310,159\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"use-case-directory\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/use-case-directory.jpg\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/use-case-directory.jpg\" class=\"size-full wp-image-1865 alignnone\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/use-case-directory.jpg\" alt=\"use-case-directory\" width=\"310\" height=\"159\" \/><\/p>\n<p>And it makes it very easy to find where certain behavior is located, or to figure out where new behavior should be put.<\/p>\n<p>All code in our <code>src\/<\/code> directory is framework independent, and all code binding to specific persistence mechanisms resides in <code>src\/DataAccess<\/code>. The only framework bound code we have are our very slim &#8220;route handlers&#8221; (kinda like controllers), the web entry point and the Silex bootstrap.<\/p>\n<p>For more information on The Clean Architecture I can recommend <a href=\"https:\/\/www.youtube.com\/watch?v=Nsjsiz2A9mg\">Robert C Martins NDC 2013 talk<\/a>. If you watch it, you will hopefully notice how we slightly deviated from the UseCase structure like he presented it. This is due to PHP being an interpreted language, and thus does not need certain interfaces that are beneficial in compiled languages.<\/p>\n<h3>Lesson learned: bounded contexts<\/h3>\n<p>By and large we started with the donation related use cases and then moved on to the membership application related ones. At some point, we had a <code>Donation<\/code> entity\/aggregate in our domain, and a bunch of value objects that it contained.<\/p>\n<pre class=\"lang:php decode:true \">class Donation {\n    private \/* int|null *\/            $id\n    private \/* PersonalInfo|null *\/   $personalInfo\n    \/* ... *\/\n}\n<\/pre>\n<pre class=\"lang:php decode:true\">class PersonalInfo {\n    private \/* PersonName *\/          $name\n    private \/* PhysicalAddress *\/     $address\n    private \/* string *\/              $emailAddress\n}<\/pre>\n<p>As you can see, one of those value objects is <code>PersonalInfo<\/code>. Then we needed to add an entity for membership applications. Like donations, membership applications require a name, a physical address and an email address. Hence it was tempting to reuse our existing <code>PersonalInfo<\/code> class.<\/p>\n<pre class=\"lang:php decode:true \">class MembershipApplication {\n    private \/* int|null *\/            $id\n    private \/* PersonalInfo|null *\/   $personalInfo\n    \/* ... *\/\n}\n<\/pre>\n<p>Luckily a complication made us realize that going down this path was not a good idea. This complication was that membership applications also have a phone number and an optional date of birth. We could have forced code sharing by doing something hacky like adding new optional fields to <code>PersonalInfo<\/code>, or by creating a <code>MorePersonalInfo<\/code> derivative.<\/p>\n<p>Approaches such as these, while resulting in some code sharing, also result in creating binding between <code>Donation<\/code> and <code>MembershipApplication<\/code>. That&#8217;s not good, as those two entities don&#8217;t have anything to do with each other. Sharing what happens to be the same at present is simply not a good idea. Just imagine that we did not have the phone number and date of birth in our first version, and then needed to add them. We&#8217;d either end up with one of those hacky solutions, or need to refactor code that has nothing to do (apart from the bad coupling) with what we want to modify.<\/p>\n<p>What we did is renaming <code>PersonalInfo<\/code> to <code>Donor<\/code> and introduce a new <code>Applicant<\/code> class.<\/p>\n<pre class=\"lang:php decode:true \">class Donor {\n    private \/* PersonName *\/          $name\n    private \/* PhysicalAddress *\/     $address\n    private \/* string *\/              $emailAddress\n}<\/pre>\n<pre class=\"lang:php decode:true\">class Applicant {\n    private \/* PersonName *\/          $name\n    private \/* PhysicalAddress *\/     $address\n    private \/* EmailAddress *\/        $email\n    private \/* PhoneNumber *\/         $phone\n    private \/* DateTime|null *\/       $dateOfBirth\n}<\/pre>\n<p>These names are better since they are about the domain (see <a href=\"https:\/\/www.agilealliance.org\/glossary\/ubiquitous-language\/\">ubiquitous language<\/a>) rather than some technical terms we needed to come up with.<\/p>\n<p>Amongst other things, this rename made us realize that we where missing some explicit boundaries in our application. The donation related code and the membership application related code where mostly independent from each other, and we agreed this was a good thing. To make it more clear that this is the case and highlight violations of that rule, we decided to reorganize our code to follow the strategic DDD pattern of <a href=\"http:\/\/martinfowler.com\/bliki\/BoundedContext.html\">Bounded Contexts<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1867\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/contexts-directory\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/contexts-directory.jpg\" data-orig-size=\"220,440\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"contexts-directory\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/contexts-directory.jpg\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/contexts-directory.jpg\" class=\"size-full wp-image-1867 alignnone\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/contexts-directory.jpg\" alt=\"contexts-directory\" width=\"220\" height=\"440\" \/><\/p>\n<p>This mainly consisted out of reorganizing our directory and namespace structure, and a few instances of splitting some code that should not have been bound together.<\/p>\n<p>Based on this we created a new diagram to reflect the high level structure of our application. <a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/09\/09\/clean-architecture-diagram\/\">This diagram, and a version with just one context<\/a>, are available for use under CC-0.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1808\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2016\/09\/09\/clean-architecture-diagram\/clean_architecture__ddd_full_application-svg\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/09\/Clean_Architecture__DDD_full_application.svg_.png\" data-orig-size=\"782,582\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Clean Architecture + Bounded Contexts\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/09\/Clean_Architecture__DDD_full_application.svg_.png\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/09\/Clean_Architecture__DDD_full_application.svg_.png\" class=\"size-full wp-image-1808 alignnone\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/09\/Clean_Architecture__DDD_full_application.svg_.png\" alt=\"Clean Architecture + Bounded Contexts\" width=\"782\" height=\"582\" \/><\/p>\n<h3>Lesson learned: validation<\/h3>\n<p>A big question we had near the start of our project was where to put validation code. Do we put it in the UCs, or in the controller-like code that calls the UCs?<\/p>\n<p>One of the first UCs we added was the one for adding donations. This one has a request model that contains a lot of information, including the donor&#8217;s name, their email, their address, the payment method, payment amount, payment interval, etc. In our domain we had several value objects for representing parts of donations, such as the donor or the payment information.<\/p>\n<pre class=\"lang:php decode:true\">class Donation {\n    private \/* int|null *\/            $id\n    private \/* Donor|null *\/          $donor\n    private \/* DonationPayment *\/     $payment\n    \/* ... *\/\n}\n\nclass Donor {\n    private \/* PersonName *\/          $name\n    private \/* PhysicalAddress *\/     $address\n    private \/* string *\/              $emailAddress\n}<\/pre>\n<p>Since we did not want to have one object with two dozen fields, and did not want to duplicate code, we used the value objects from our domain in the request model.<\/p>\n<pre class=\"lang:php decode:true\">class AddDonationRequest {\n    private \/* Donor|null *\/          $donor\n    private \/* DonationPayment *\/     $payment\n    \/* ... *\/\n}<\/pre>\n<p>If you&#8217;ve been paying attention, you&#8217;ll have realized that this approach violates one of the earlier outlined rules: nothing outside the UC layer is supposed to access anything from the domain. If value objects from the domain are exposed to whatever constructs the request model, i.e. a controller, this rule is violated. Loose from the this abstract objection, we got into real trouble by doing this.<\/p>\n<p>Since we started doing validation in our UCs, this usage of objects from the domain in the request necessarily forced those objects to allow invalid values. For instance, if we&#8217;re validating the validity of an email address in the UC (or a service used by the UC), then the request model cannot use an <code>EmailAddress<\/code> which does sanity checks in its constructor.<\/p>\n<p>We thus refactored our code to avoid using any of our domain objects in the request models (and response models), so that those objects could contain basic safeguards.<\/p>\n<p>We made a similar change by altering which objects get validated. At the start of our project we created a number of validators that worked on objects from the domain. For instance a <code>DonationValidator<\/code> working with the <code>Donation<\/code> Entity. This <code>DonationValidator<\/code> would then be used by the <code>AddDonationUseCase<\/code>. This is not a good idea, since the validation that needs to happen depends on the context. In the <code>AddDonationUseCase<\/code> certain restrictions apply that don&#8217;t always hold for donations. Hence having a general looking <code>DonationValidator<\/code> is misleading. What we ended up doing instead is having validation code specific to the UCs, be it as part of the UC, or when too complex, a separate validation service in the same namespace. In both cases the validation code would work on the request model, i.e. <code>AddDonationRequest<\/code>, and not bind to the domain.<\/p>\n<p>After learning these two lessons, we had a nice approach for policy-based validation. That&#8217;s not all validation that needs to be done though. For instance, if you get a number via a web request, the framework will typically give it to you as a string, which might thus not be an actual number. As the request model is supposed to be presentation mechanism agnostic, certain validation, conversion and error handling needs to happen before constructing the request model and invoking the UC. This means that often you will have validation in two places: policy based validation in the UC, and presentation specific validation in your controllers or equivalent code. If you have a string to integer conversion, number parsing or something internationalization specific, in your UC, you almost certainly messed up.<\/p>\n<h3>Closing notes<strong><br \/>\n<\/strong><\/h3>\n<p>You can find the Wikimedia Deutschland fundraising application <a href=\"https:\/\/github.com\/wmde\/FundraisingFrontend\">on GitHub<\/a> and see it running <a href=\"https:\/\/spenden.wikimedia.de\/\">in production<\/a>. Unfortunately the code of the old application is not available for comparison, as it is not public. If you have questions, you can leave a comment, or <a href=\"https:\/\/www.entropywins.wtf\/\">contact me<\/a>. If you find an issue or want to contribute, you can <a href=\"https:\/\/github.com\/wmde\/FundraisingFrontend\/pulls\">create a pull request<\/a>. If you are looking for my presentation on this topic, <a href=\"https:\/\/entropywins.wtf\/slides\/fun-architecture\">view the slides<\/a>.<\/p>\n<p>As a team we learned a lot during this project, and we set a number of firsts at <a href=\"http:\/\/software.wikimedia.de\/\">Wikimedia Deutschland<\/a>, or the wider Wikimedia movement for that matter. The new codebase is the cleanest non-trivial application we have, or that I know of in PHP world. It is fully tested, contains less than 5% framework bound code, has strong strategic separation between both contexts and layers, has roughly 5% data access specific code and has tests that can be run without any real setup. (I might write another blog post on how we designed our tests and testing environment.)<\/p>\n<p>Many thanks for my colleagues\u00a0<a href=\"https:\/\/github.com\/KaiNissen\">Kai Nissen<\/a> and <a href=\"https:\/\/github.com\/gbirke\">Gabriel Birke<\/a> for being pretty awesome during our rewrite project.<\/p>\n<h3>Further reading<\/h3>\n<p>Sign up below to receive news on my upcoming Clean Architecture book, including a discount.<\/p>\n<div id=\"mc_embed_signup\">\n<form id=\"mc-embedded-subscribe-form\" class=\"validate\" action=\"https:\/\/wtf.us19.list-manage.com\/subscribe\/post?u=5e9453f7bede9f5b0220b2c42&amp;id=9df25d9e9d\" method=\"post\" name=\"mc-embedded-subscribe-form\" novalidate=\"\" target=\"_blank\">\n<div id=\"mc_embed_signup_scroll\">\n<div class=\"mc-field-group\"><input id=\"mce-EMAIL\" class=\"required email\" name=\"EMAIL\" type=\"email\" value=\"\" placeholder=\"Your email address\" \/><\/div>\n<div id=\"mce-responses\" class=\"clear\">\n<div id=\"mce-error-response\" class=\"response\" style=\"display: none;\"><\/div>\n<div id=\"mce-success-response\" class=\"response\" style=\"display: none;\"><\/div>\n<\/div>\n<div style=\"position: absolute; left: -5000px;\" aria-hidden=\"true\"><input tabindex=\"-1\" name=\"b_5e9453f7bede9f5b0220b2c42_9df25d9e9d\" type=\"text\" value=\"\" \/><\/div>\n<div class=\"clear\"><input id=\"mc-embedded-subscribe\" class=\"button\" name=\"subscribe\" type=\"submit\" value=\"Subscribe\" \/><\/div>\n<\/div>\n<\/form>\n<\/div>\n<p>Other things to look at:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/14\/clean-architecture-bounded-contexts\/\">Clean Architecture + Bounded Contexts<\/a><\/li>\n<li><a href=\"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/14\/bounded-contexts-in-the-wikimedia-fundraising-software\/\">Bounded Contexts in the Wikimedia Fundraising Software<\/a><\/li>\n<li><a href=\"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/01\/clean-architecture-usecase-tests\/\">Clean Architecture: UseCase tests<\/a><\/li>\n<li><a href=\"https:\/\/www.goodreads.com\/book\/show\/18043011-clean-architecture\">Clean Architecture<\/a>, Robert C. Martin, 2016<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Both Domain Driven Design and architectures such as the Clean Architecture and Hexagonal are often talked about. It&#8217;s hard to&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[7],"tags":[429,328,373,405,195,197,215,430,316,427,285,336],"class_list":["post-1846","post","type-post","status-publish","format-standard","hentry","category-programming","tag-clean-architecture","tag-clean-code","tag-design-patterns","tag-domain-driven-design","tag-php","tag-planet-wikimedia","tag-refactoring","tag-software-architecture","tag-software-design","tag-strategic-design","tag-wikimedia","tag-wmde"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Implementing the Clean Architecture - Blog of Jeroen De Dauw<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Implementing the Clean Architecture - Blog of Jeroen De Dauw\" \/>\n<meta property=\"og:description\" content=\"Both Domain Driven Design and architectures such as the Clean Architecture and Hexagonal are often talked about. It&#8217;s hard to&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog of Jeroen De Dauw\" \/>\n<meta property=\"article:published_time\" content=\"2016-11-24T17:22:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-02-23T05:11:21+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\" \/>\n<meta name=\"author\" content=\"Jeroen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/JeroenDeDauw\" \/>\n<meta name=\"twitter:site\" content=\"@JeroenDeDauw\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeroen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\"},\"author\":{\"name\":\"Jeroen\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"headline\":\"Implementing the Clean Architecture\",\"datePublished\":\"2016-11-24T17:22:07+00:00\",\"dateModified\":\"2019-02-23T05:11:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\"},\"wordCount\":1968,\"commentCount\":41,\"publisher\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"image\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\",\"keywords\":[\"Clean Architecture\",\"Clean Code\",\"Design patterns\",\"Domain Driven Design\",\"PHP\",\"Planet Wikimedia\",\"Refactoring\",\"Software Architecture\",\"Software design\",\"Strategic Design\",\"Wikimedia\",\"WMDE\"],\"articleSection\":[\"Programming\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\",\"url\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\",\"name\":\"Implementing the Clean Architecture - Blog of Jeroen De Dauw\",\"isPartOf\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\",\"datePublished\":\"2016-11-24T17:22:07+00:00\",\"dateModified\":\"2019-02-23T05:11:21+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#primaryimage\",\"url\":\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\",\"contentUrl\":\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg\",\"width\":772,\"height\":567},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.entropywins.wtf\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Implementing the Clean Architecture\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#website\",\"url\":\"https:\/\/www.entropywins.wtf\/blog\/\",\"name\":\"Entropy Wins\",\"description\":\"A blog on Software Architecture, Design and Craftsmanship\",\"publisher\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.entropywins.wtf\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7\",\"name\":\"Jeroen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\",\"caption\":\"Jeroen\"},\"logo\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/image\/\"},\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/jeroendedauw\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/JeroenDeDauw\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Implementing the Clean Architecture - Blog of Jeroen De Dauw","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/","og_locale":"en_US","og_type":"article","og_title":"Implementing the Clean Architecture - Blog of Jeroen De Dauw","og_description":"Both Domain Driven Design and architectures such as the Clean Architecture and Hexagonal are often talked about. It&#8217;s hard to&hellip;","og_url":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/","og_site_name":"Blog of Jeroen De Dauw","article_published_time":"2016-11-24T17:22:07+00:00","article_modified_time":"2019-02-23T05:11:21+00:00","og_image":[{"url":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg","type":"","width":"","height":""}],"author":"Jeroen","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/JeroenDeDauw","twitter_site":"@JeroenDeDauw","twitter_misc":{"Written by":"Jeroen","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#article","isPartOf":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/"},"author":{"name":"Jeroen","@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"headline":"Implementing the Clean Architecture","datePublished":"2016-11-24T17:22:07+00:00","dateModified":"2019-02-23T05:11:21+00:00","mainEntityOfPage":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/"},"wordCount":1968,"commentCount":41,"publisher":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"image":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#primaryimage"},"thumbnailUrl":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg","keywords":["Clean Architecture","Clean Code","Design patterns","Domain Driven Design","PHP","Planet Wikimedia","Refactoring","Software Architecture","Software design","Strategic Design","Wikimedia","WMDE"],"articleSection":["Programming"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/","url":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/","name":"Implementing the Clean Architecture - Blog of Jeroen De Dauw","isPartOf":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#primaryimage"},"image":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#primaryimage"},"thumbnailUrl":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg","datePublished":"2016-11-24T17:22:07+00:00","dateModified":"2019-02-23T05:11:21+00:00","breadcrumb":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#primaryimage","url":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg","contentUrl":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg","width":772,"height":567},{"@type":"BreadcrumbList","@id":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.entropywins.wtf\/blog\/"},{"@type":"ListItem","position":2,"name":"Implementing the Clean Architecture"}]},{"@type":"WebSite","@id":"https:\/\/www.entropywins.wtf\/blog\/#website","url":"https:\/\/www.entropywins.wtf\/blog\/","name":"Entropy Wins","description":"A blog on Software Architecture, Design and Craftsmanship","publisher":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.entropywins.wtf\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7","name":"Jeroen","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g","caption":"Jeroen"},"logo":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/in\/jeroendedauw\/","https:\/\/x.com\/https:\/\/twitter.com\/JeroenDeDauw"]}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p74TBF-tM","jetpack-related-posts":[{"id":2210,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/14\/clean-architecture-bounded-contexts\/","url_meta":{"origin":1846,"position":0},"title":"Clean Architecture + Bounded Contexts","author":"Jeroen","date":"2018-08-14","format":false,"excerpt":"In this follow-up to Implementing the Clean Architecture I introduce you to a combination of The Clean Architecture and the strategic DDD pattern known as Bounded Contexts. At Wikimedia Deutschland we use this combination of The Clean Architecture and Bounded Contexts for our fundraising applications. In this post I describe\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/CleanArchitecture_DomainDrivenDesign.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":2278,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/14\/bounded-contexts-in-the-wikimedia-fundraising-software\/","url_meta":{"origin":1846,"position":1},"title":"Bounded Contexts in the Wikimedia Fundraising Software","author":"Jeroen","date":"2018-08-14","format":false,"excerpt":"In this follow-up to rewriting the Wikimedia Deutschland fundraising I tell the story of how we reorganized our codebases along the lines of the DDD strategic pattern Bounded Contexts. In 2016 the FUN team at Wikimedia Deutschland rewrote the Wikimedia Deutschland fundraising application. This new codebase uses The Clean Architecture\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"Diagram depicting Clean Architecture + Bounded Contexts","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/08\/Such-Clean-Diagram.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":2358,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/09\/09\/clean-architecture-bounded-contexts-diagram\/","url_meta":{"origin":1846,"position":2},"title":"Clean Architecture + Bounded Contexts diagram","author":"Jeroen","date":"2018-09-09","format":false,"excerpt":"I\u2019m happy to release a two Clean Architecture + Bounded Contexts diagrams into the public domain (CC0 1.0). I created these diagrams for Wikimedia Deutchland with the help of Jan Dittrich, Charlie Kritschmar and Hanna Petruschat. They represent the architecture of our fundraising codebase. I explain the rules of this\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/09\/FunArchitecture.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":2219,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/05\/09\/guidelines-for-new-software-projects\/","url_meta":{"origin":1846,"position":3},"title":"Guidelines for New Software Projects","author":"Jeroen","date":"2018-05-09","format":false,"excerpt":"In this blog post I share the Guidelines for New Software Projects that we use at Wikimedia Deutschland. I wrote down these guidelines recently after a third-party that was contracted by Wikimedia Deutschland delivered software that was problematic in several ways. The department contracting this third-party was not the software\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1841,"url":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/rewriting-the-wikimedia-deutschland-funrdraising\/","url_meta":{"origin":1846,"position":4},"title":"Rewriting the Wikimedia Deutschland fundraising","author":"Jeroen","date":"2016-11-24","format":false,"excerpt":"Last year we rewrote the Wikimedia Deutschland fundraising software. In this blog post I'll give you an idea of what this software does, why we rewrote it and the outcome of this rewrite. The application Our fundraising software is a homegrown PHP application. Its primary functions are donations and membership\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/lloc-per-global.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/lloc-per-global.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/lloc-per-global.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/lloc-per-global.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1807,"url":"https:\/\/www.entropywins.wtf\/blog\/2016\/09\/09\/clean-architecture-diagram\/","url_meta":{"origin":1846,"position":5},"title":"Clean Architecture diagrams","author":"Jeroen","date":"2016-09-09","format":false,"excerpt":"I'm happy to release a few Clean Architecture related diagrams into the public domain (CC0 1.0). Update 2018-9-9: new diagrams featuring Bounded Contexsts are now available! These diagrams where created at Wikimedia Deutchland by Jan Dittrich, Charlie Kritschmar and myself for an upcoming presentation I'm doing on the Clean Architecture.\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/09\/Clean_Architecture_core.svg_.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/09\/Clean_Architecture_core.svg_.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/09\/Clean_Architecture_core.svg_.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/1846","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/comments?post=1846"}],"version-history":[{"count":31,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/1846\/revisions"}],"predecessor-version":[{"id":2488,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/1846\/revisions\/2488"}],"wp:attachment":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/media?parent=1846"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/categories?post=1846"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/tags?post=1846"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}