{"id":2495,"date":"2019-02-28T08:38:47","date_gmt":"2019-02-28T07:38:47","guid":{"rendered":"https:\/\/www.entropywins.wtf\/blog\/?p=2495"},"modified":"2021-08-27T16:47:38","modified_gmt":"2021-08-27T15:47:38","slug":"applications-as-frameworks","status":"publish","type":"post","link":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/","title":{"rendered":"Applications as Frameworks"},"content":{"rendered":"<p>What are the differences between building on top of a framework and building on top of an application? How does using an application as a framework cause problems, and how can these problems be avoided? That is what this post is all about.<\/p>\n<h3>Decoupled web application<\/h3>\n<p>In your typical web application, the code handles a request and returns a response. Let&#8217;s assume we are using a web framework to handle common tasks such as routing. Let&#8217;s also assume that we think framework binding has a high cost, and are thus decoupling our application from the framework. The flow of control would look like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2498\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/frameworkandapp\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndApp.png\" data-orig-size=\"438,280\" 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=\"Framework and application\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndApp.png\" class=\"alignnone wp-image-2498\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndApp.png\" alt=\"\" width=\"438\" height=\"280\" \/><\/p>\n<p>Execution starts with the framework. For PHP frameworks this will be in a file like <code>public\/index.php<\/code>. The framework then bootstraps itself and does a bunch of stuff. It&#8217;s safe to assume this stuff will include routing, and often it also includes things like dependency construction and error handling.<\/p>\n<p>After the framework did the tasks you want it to do, it hands control over to your application. Your application does a bunch of application and domain logic and interacts with persistence. It likely uses a number of libraries, especially for infrastructure tasks like logging and database access. Even so, control stays with the application. (The key difference between frameworks and libraries is that you control\/call libraries while frameworks control\/call you.) Your application might also be calling the framework and use it as a library. Again, control stays with the application.<\/p>\n<p>Finally when the application is done, it hands some kinda of result back to the framework. The framework then does another bunch of stuff, like template rendering and translations. In case of a web framework it then spits out a HTTP response and execution ends.<\/p>\n<p>An application like this keeps you in control of what happens, making it easier to change things. This style also makes it easy to decouple from the framework. There are only two points where you need to decouple.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2500\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/frameworkandapphighlight\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndAppHighlight.png\" data-orig-size=\"438,280\" 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=\"Framework and application interaction\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndAppHighlight.png\" class=\"alignnone size-full wp-image-2500\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndAppHighlight.png\" alt=\"\" width=\"438\" height=\"280\" \/><\/p>\n<p>My post <a href=\"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/\">Implementing The Clean Architecture<\/a> outlines one architectural approach that leads to this kind of application.<\/p>\n<h3>Frameworks vs Applications<\/h3>\n<p>Let&#8217;s compare how frameworks and applications differ when they are used as a foundation for an\/another application.<\/p>\n<p>Frameworks don&#8217;t do stuff on their own. There is no application or domain logic. There is no set of existing web pages or API endpoints with their own structure and behavior. This is all defined by your application when using a framework. When building on top of an application that acts as a framework, you&#8217;ll need to deal with existing structure and behavior. You&#8217;ll need to insert your own stuff, change existing behavior in certain situations and prevent default behavior altogether in others.<\/p>\n<p>I know that there are &#8220;frameworks&#8221; that do provide their own stuff out of the box. (Example: web shop framework.) While they might not be a full application on their own, for the purpose of this blog post they are the same as an application that gets used as a framework.<\/p>\n<h3>Plugins and Extensions<\/h3>\n<p>There is nothing inherently bad about building things on top of an application. Plugins and extensions are a very useful pattern. A plugin that interacts with a single plugin point can decouple itself when appropriate, and it is in control over itself. For smaller plugins that use many plugins points, framework decoupling might not be feasible or worth the effort.<\/p>\n<p>This post is about using applications as framework foundation for sizable sets of code which are applications in their own right.<\/p>\n<h3>Applications as Frameworks<\/h3>\n<p>Let&#8217;s imagine we have an application that is used on some site for some use case. We&#8217;ll call this application FrameworkApp, since we&#8217;ll use it as framework for another application that powers another site.<\/p>\n<p>When building our application on top of FrameworkApp, we&#8217;ll need to register new behavior and modify existing behavior. To make this possible, FrameworkApp needs to provide the appropriate extension points. Often these take the form of abstract classes or even systems, though the exact nature of the extension points is not important for our purposes.<\/p>\n<p>This leads to a very different flow of control. Rather than calling us once, the FrameworkApp calls each extension point our application handles.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2502\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/appasframework\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/AppAsFramework.png\" data-orig-size=\"438,280\" 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=\"Application as framework\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/AppAsFramework.png\" class=\"alignnone size-full wp-image-2502\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/AppAsFramework.png\" alt=\"\" width=\"438\" height=\"280\" \/><\/p>\n<p>The diagram is showing just 6 extension points, though there can be 100s.<\/p>\n<p>When visualized like this, it becomes easy to see how decoupling from the framework becomes almost impossible. Even if you manage to avoid coupling to framework <em>code<\/em> in your application, <strong>its whole structure is<\/strong> still <strong>defined by the framework<\/strong>. This means you are very limited in what you can do in your application and need to understand the framework to effectively develop the application. Framework coupling causes more issues than that, though a comprehensive overview of those is out of scope for this post.<\/p>\n<h3>An OOP Solution<\/h3>\n<blockquote><p>Favor composition over inheritance<\/p>\n<p><small>&#8212; OOP principle<\/small><\/p><\/blockquote>\n<p>Using an application as a framework is very similar to using inheritance for code reuse.<\/p>\n<p>Just like with the application that is build on top of the app that acts as framework, the subclass might not be in control and be invoked many times from the base class. This is especially the case when using the Template Method Pattern and when having a deep inheritance hierarchy. The flow of control can bounce all over the place and decoupling the subclass from the classes up the hierarchy becomes all but impossible.<\/p>\n<p>You can avoid this classical inheritance mess by using composition. Which suggests one way to move away from using an application as a framework or avoid doing so altogether: stop treating the framework as a base class. If there is code to share, use composition. This way you stay in control, can decouple easier and avoid <a href=\"https:\/\/www.entropywins.wtf\/blog\/2017\/09\/06\/the-fallacy-of-dry\/\">The Fallacy of DRY<\/a>.<\/p>\n<p>Just like with class hierarchies you can always slap on an extra level.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2504\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/no\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/NO.png\" data-orig-size=\"663,280\" 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=\"NO\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/NO.png\" class=\"alignnone wp-image-2504\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/NO.png\" alt=\"\" width=\"592\" height=\"250\" \/> <img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2505\" data-permalink=\"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/grumpy-cat-no\/\" data-orig-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/grumpy-cat-no.jpg\" data-orig-size=\"680,531\" 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=\"NO\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/grumpy-cat-no.jpg\" class=\"alignnone wp-image-2505\" src=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/grumpy-cat-no.jpg\" alt=\"\" width=\"321\" height=\"250\" \/><\/p>\n<h3>Don&#8217;t miss the book!<\/h3>\n<script>(function() {\n\twindow.mc4wp = window.mc4wp || {\n\t\tlisteners: [],\n\t\tforms: {\n\t\t\ton: function(evt, cb) {\n\t\t\t\twindow.mc4wp.listeners.push(\n\t\t\t\t\t{\n\t\t\t\t\t\tevent   : evt,\n\t\t\t\t\t\tcallback: cb\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n})();\n<\/script><!-- Mailchimp for WordPress v4.12.1 - https:\/\/wordpress.org\/plugins\/mailchimp-for-wp\/ --><form id=\"mc4wp-form-1\" class=\"mc4wp-form mc4wp-form-2484\" method=\"post\" data-id=\"2484\" data-name=\"Implementing the Clean Architecture\" ><div class=\"mc4wp-form-fields\">Sign up below to receive news on my upcoming Clean Architecture book, including a discount:\r\n<div id=\"mc_embed_signup\">\r\n<div id=\"mc_embed_signup_scroll\">\r\n<div class=\"mc-field-group\"><input id=\"mce-EMAIL\" class=\"required email\" name=\"EMAIL\" type=\"email\" value=\"\" placeholder=\"Your email address\" \/><\/div>\r\n<div id=\"mce-responses\" class=\"clear\">\r\n<div id=\"mce-error-response\" class=\"response\" style=\"display: none;\"><\/div>\r\n<div id=\"mce-success-response\" class=\"response\" style=\"display: none;\"><\/div>\r\n<\/div>\r\n<div style=\"position: absolute; left: -5000px;\" aria-hidden=\"true\"><input tabindex=\"-1\" name=\"b_5e9453f7bede9f5b0220b2c42_9df25d9e9d\" type=\"text\" value=\"\" \/><\/div>\r\n<div class=\"clear\"><input id=\"mc-embedded-subscribe\" class=\"button\" name=\"subscribe\" type=\"submit\" value=\"Subscribe\" \/><\/div>\r\n<\/div>\r\n<\/div><\/div><label style=\"display: none !important;\">Leave this field empty if you're human: <input type=\"text\" name=\"_mc4wp_honeypot\" value=\"\" tabindex=\"-1\" autocomplete=\"off\" \/><\/label><input type=\"hidden\" name=\"_mc4wp_timestamp\" value=\"1777562916\" \/><input type=\"hidden\" name=\"_mc4wp_form_id\" value=\"2484\" \/><input type=\"hidden\" name=\"_mc4wp_form_element_id\" value=\"mc4wp-form-1\" \/><div class=\"mc4wp-response\"><\/div><\/form><!-- \/ Mailchimp for WordPress Plugin -->\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What are the differences between building on top of a framework and building on top of an application? How does&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":false,"_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":[331,328,442,462,197,430,316],"class_list":["post-2495","post","type-post","status-publish","format-standard","hentry","category-programming","tag-architecture","tag-clean-code","tag-coupling","tag-frameworks","tag-planet-wikimedia","tag-software-architecture","tag-software-design"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Applications as Frameworks - Blog of Jeroen De Dauw<\/title>\n<meta name=\"description\" content=\"What are the difference between applications and frameworks, how can applications be used as frameworks and how can common problems be avoided?\" \/>\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\/2019\/02\/28\/applications-as-frameworks\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Applications as Frameworks\" \/>\n<meta property=\"og:description\" content=\"What are the difference between applications and frameworks and how can applications be used as frameworks\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog of Jeroen De Dauw\" \/>\n<meta property=\"article:published_time\" content=\"2019-02-28T07:38:47+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-08-27T15:47:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/AppAsFramework.png\" \/>\n\t<meta property=\"og:image:width\" content=\"438\" \/>\n\t<meta property=\"og:image:height\" content=\"280\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Jeroen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Applications as Frameworks\" \/>\n<meta name=\"twitter:description\" content=\"What are the difference between applications and frameworks and how can applications be used as frameworks\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/AppAsFramework.png\" \/>\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=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/\"},\"author\":{\"name\":\"Jeroen\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#\\\/schema\\\/person\\\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"headline\":\"Applications as Frameworks\",\"datePublished\":\"2019-02-28T07:38:47+00:00\",\"dateModified\":\"2021-08-27T15:47:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/\"},\"wordCount\":991,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#\\\/schema\\\/person\\\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"image\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/02\\\/FrameworkAndApp.png\",\"keywords\":[\"Architecture\",\"Clean Code\",\"Coupling\",\"Frameworks\",\"Planet Wikimedia\",\"Software Architecture\",\"Software design\"],\"articleSection\":[\"Programming\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/\",\"url\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/\",\"name\":\"Applications as Frameworks - Blog of Jeroen De Dauw\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/02\\\/FrameworkAndApp.png\",\"datePublished\":\"2019-02-28T07:38:47+00:00\",\"dateModified\":\"2021-08-27T15:47:38+00:00\",\"description\":\"What are the difference between applications and frameworks, how can applications be used as frameworks and how can common problems be avoided?\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/02\\\/FrameworkAndApp.png\",\"contentUrl\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/02\\\/FrameworkAndApp.png\",\"width\":438,\"height\":280},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/2019\\\/02\\\/28\\\/applications-as-frameworks\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.entropywins.wtf\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Applications as Frameworks\"}]},{\"@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:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\",\"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:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\"},\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/jeroendedauw\\\/\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/JeroenDeDauw\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Applications as Frameworks - Blog of Jeroen De Dauw","description":"What are the difference between applications and frameworks, how can applications be used as frameworks and how can common problems be avoided?","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\/2019\/02\/28\/applications-as-frameworks\/","og_locale":"en_US","og_type":"article","og_title":"Applications as Frameworks","og_description":"What are the difference between applications and frameworks and how can applications be used as frameworks","og_url":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/","og_site_name":"Blog of Jeroen De Dauw","article_published_time":"2019-02-28T07:38:47+00:00","article_modified_time":"2021-08-27T15:47:38+00:00","og_image":[{"width":438,"height":280,"url":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/AppAsFramework.png","type":"image\/png"}],"author":"Jeroen","twitter_card":"summary_large_image","twitter_title":"Applications as Frameworks","twitter_description":"What are the difference between applications and frameworks and how can applications be used as frameworks","twitter_image":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/AppAsFramework.png","twitter_creator":"@https:\/\/twitter.com\/JeroenDeDauw","twitter_site":"@JeroenDeDauw","twitter_misc":{"Written by":"Jeroen","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/#article","isPartOf":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/"},"author":{"name":"Jeroen","@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"headline":"Applications as Frameworks","datePublished":"2019-02-28T07:38:47+00:00","dateModified":"2021-08-27T15:47:38+00:00","mainEntityOfPage":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/"},"wordCount":991,"commentCount":0,"publisher":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"image":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/#primaryimage"},"thumbnailUrl":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndApp.png","keywords":["Architecture","Clean Code","Coupling","Frameworks","Planet Wikimedia","Software Architecture","Software design"],"articleSection":["Programming"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/","url":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/","name":"Applications as Frameworks - Blog of Jeroen De Dauw","isPartOf":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/#primaryimage"},"image":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/#primaryimage"},"thumbnailUrl":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndApp.png","datePublished":"2019-02-28T07:38:47+00:00","dateModified":"2021-08-27T15:47:38+00:00","description":"What are the difference between applications and frameworks, how can applications be used as frameworks and how can common problems be avoided?","breadcrumb":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/#primaryimage","url":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndApp.png","contentUrl":"https:\/\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2019\/02\/FrameworkAndApp.png","width":438,"height":280},{"@type":"BreadcrumbList","@id":"https:\/\/www.entropywins.wtf\/blog\/2019\/02\/28\/applications-as-frameworks\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.entropywins.wtf\/blog\/"},{"@type":"ListItem","position":2,"name":"Applications as Frameworks"}]},{"@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:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g","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:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g"},"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-Ef","jetpack-related-posts":[{"id":2219,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/05\/09\/guidelines-for-new-software-projects\/","url_meta":{"origin":2495,"position":0},"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":2210,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/08\/14\/clean-architecture-bounded-contexts\/","url_meta":{"origin":2495,"position":1},"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":1846,"url":"https:\/\/www.entropywins.wtf\/blog\/2016\/11\/24\/implementing-the-clean-architecture\/","url_meta":{"origin":2495,"position":2},"title":"Implementing the Clean Architecture","author":"Jeroen","date":"2016-11-24","format":false,"excerpt":"Both Domain Driven Design and architectures such as the Clean Architecture and Hexagonal are often talked about. It'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'll\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\/CleanArchitecture.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2016\/11\/CleanArchitecture.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1966,"url":"https:\/\/www.entropywins.wtf\/blog\/2017\/02\/17\/why-every-single-argument-of-dan-north-is-wrong\/","url_meta":{"origin":2495,"position":3},"title":"Why Every Single Argument of Dan North is Wrong","author":"Jeroen","date":"2017-02-17","format":false,"excerpt":"This blog post is a reply to Dan's presentation Why Every Element of SOLID is Wrong. Dan's presentation is crammed full with straw man argumentation in which he misinterprets what the SOLID principles are about. After refuting each principle he proposes an alternative, typically a well-accepted non-SOLID principle that does\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\/2017\/02\/slide_19.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2017\/02\/slide_19.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2017\/02\/slide_19.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2017\/02\/slide_19.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":809,"url":"https:\/\/www.entropywins.wtf\/blog\/2010\/05\/01\/bn-converter-pro-1-1-0-released\/","url_meta":{"origin":2495,"position":4},"title":"BN+ Converter Pro 1.1.0 released","author":"Jeroen","date":"2010-05-01","format":false,"excerpt":"Two months back I dug up the project files of BN+ Converter Pro, a .Net application I created when I was in secondary school, and did some high level refactoring to optimize it for .Net 4.0 and version 3 of my .Net class library. This was soon after I released\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"BN+ Converter Pro 1.0.6","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2010\/05\/Bnc1.0.6.gif?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":27,"url":"https:\/\/www.entropywins.wtf\/blog\/2009\/05\/21\/bn-framework-2-0-3-released\/","url_meta":{"origin":2495,"position":5},"title":"BN+ Framework 2.0.3 released","author":"Jeroen","date":"2009-05-21","format":false,"excerpt":"I\u2019ve just released a new version of BN+ framework. It features a variety of new classes since version 2.0.2 plus some bug fixes and stability improvements. Also some classes have been added the the class library or control library repositories on BN+ Discussions, and a few of them now have\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":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/2495","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=2495"}],"version-history":[{"count":17,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/2495\/revisions"}],"predecessor-version":[{"id":2839,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/2495\/revisions\/2839"}],"wp:attachment":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/media?parent=2495"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/categories?post=2495"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/tags?post=2495"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}