{"id":525,"date":"2017-10-28T11:14:48","date_gmt":"2017-10-28T09:14:48","guid":{"rendered":"http:\/\/agilerasmus.com\/wordpress\/?p=525"},"modified":"2017-10-28T11:14:48","modified_gmt":"2017-10-28T09:14:48","slug":"feature-toggles","status":"publish","type":"post","link":"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/","title":{"rendered":"Feature Toggles"},"content":{"rendered":"<p>Back in 2007 I wrote an <a href=\"https:\/\/www.codeproject.com\/Articles\/19494\/Refactoring-Without-Starting-Over\">article<\/a> on how to\u00a0prepare your code for refactoring without tampering with legacy code that needs to remain intact. Recently I have found that this\u00a0design pattern may be useful for other purposes, in particular <a href=\"https:\/\/martinfowler.com\/articles\/feature-toggles.html\">feature toggling<\/a> as described by Martin Fowler. Feature toggling is key to delivering <a href=\"https:\/\/guntherverheyen.com\/2015\/03\/13\/releasable-in-scrum-actually\/\">potential releasable software<\/a> after each sprint when applying the Scrum framework in enterprise organisations.<\/p>\n<p>Below is a retouched version of the original article written back when I was developing C and C++ software for <a href=\"https:\/\/da.systematic.com\/\">Systematic<\/a>. Even though the code samples are written in C the basic pattern applies to all programming languages ranging from Cobol to Java.<\/p>\n<h2>Scope of the problem<\/h2>\n<p>Imagine this: for some odd reason, you end up in a situation where you have a big pile of spaghetti code (also known as legacy code) and you have a feature request to radically extend the functionality of the big pile. How do you go about this? Obviously, there are at least the three following approaches to the problem:<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li>Deny the request.<\/li>\n<li>Hack the legacy code to cope with the request.<\/li>\n<li>Refactor the legacy code to meet new coding standards.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>Cases 1 and 2 have an immediate short term effect. Case 1 &#8211; no money is earned and the customer might be lost for good. Case 2 &#8211; the money is safe; however, further development and maintenance will (over time) be awfully painful. Case 3 is the ideal solution, and would be the choice of most developers and the worst case scenario of most CEOs: it has a radical short term economical impact, and could drag the development process on for ages.<\/p>\n<p>However, there is also a fourth option:<\/p>\n<ul>\n<li>Turn the legacy &#8220;interface&#8221; into a combination of Facade and Adapter patterns.<\/li>\n<li>Introduce a data driven run time configuration to toggle the feature depending on context<\/li>\n<\/ul>\n<p>This option will leave most of the legacy code base intact, while only introducing a light weight abstraction layer. This may sound fuzzy at the moment, but in the remainder of this article, I will give an introduction to how to refactor legacy code without rewriting the code.<\/p>\n<p>Going back to case 2, where we would refactor the code base to suit the newly found requirements, changes are introduced at the location of the new feature code and also at the location of all the calling applications. This is a cumbersome solution, and is likely to introduce bugs in portions of the program that used to work flawlessly. However, the method described in this article will try to describe a method of implementing new features without tampering with the legacy interface. This means that all calling applications remain unmodified, but with access to the new feature code hidden by a facade.<\/p>\n<h2>Design Patterns<\/h2>\n<p>First, what is a facade pattern? Googling on Wikipedia, we will find the following definition:<\/p>\n<blockquote><p>In computer programming, a facade is an object that provides a simplified interface to a larger body of code, such as a class library.<\/p>\n<ul>\n<li>Make a software library easier to use and understand, since the facade has convenient methods for common tasks.<\/li>\n<li>Make code that uses the library more readable, for the same reason.<\/li>\n<li>Reduce dependencies of outside code on the inner workings of a library, since most code uses the facade, thus allowing more flexibility in developing the system.<\/li>\n<li>Wrap a poorly designed collection of APIs with a single well-designed API.<\/li>\n<\/ul>\n<\/blockquote>\n<p>Second, what is the Adapter pattern? Again, googling Wikipedia will tell us:<\/p>\n<blockquote><p>In computer programming, the Adapter design pattern (sometimes referred to as the wrapper pattern, or simply a wrapper) &#8216;adapts&#8217; one interface for a class into one that a client expects. An adapter allows classes to work together that normally could not because of incompatible interfaces, by wrapping its own interface around that of an already existing class.<\/p><\/blockquote>\n<p>These two structural patterns are per definition generic, and can be applied to any code developed. At scope level, it is most suitable to deploy such patterns while designing and implementing a component, and not while adding features to existing components. Many programmers have to deal with source code written in an era before the Design Patterns, and thus no patterns have been intentionally applied. Introducing or identifying such patterns will often require a costly rewrite or a major refactoring of the code base. In the following section, we will discuss possible ways of refactoring at minimum cost.<\/p>\n<p>These two structural patterns are per definition generic and can be applied to any code developed. At scope level it is most suitable to deploy such patterns while designing and implementing a component and not while adding features to existing components. Many programmers have to deal with source code written in an era before the design patterns and thus no patterns have been intentionally applied. Introducing or identifying such patterns will often require a costly rewrite or a major refactorization of the code base. In the following section, we will discuss possible ways of refactoring at minimum cost.<\/p>\n<h2>Introducing the patterns<\/h2>\n<p>The first step in the process of preparing the legacy code base for the new component feature is to identify all feasible entry points. Looking at a legacy code base, there are two basic constructs of how the code is interacting:<\/p>\n<h3>1. Multiple clients one entry point<\/h3>\n<p>The first step in the process of preparing the legacy code base for the new component feature is to identify all feasible entry points. Looking at a legacy code base, there are two basic constructs of how the code is interacting:<\/p>\n<p><img loading=\"lazy\" src=\"https:\/\/i0.wp.com\/www.codeproject.com\/KB\/architecture\/refactoring\/facade.png?resize=269%2C266&#038;ssl=1\" width=\"269\" height=\"266\" data-recalc-dims=\"1\" \/><\/p>\n<p>Figure 1: Multiple clients, one entry point, demonstrates the simplest scenario, a code base with a (more or less) well defined interface. The interface may consist of a range of free functions, or be centralized in a common class. In both cases, the code structure already holds a derivate of the Facade pattern and is ready for modifications.<\/p>\n<h3>2. Multiple clients and multiple entry points<\/h3>\n<p><img loading=\"lazy\" src=\"https:\/\/i2.wp.com\/www.codeproject.com\/KB\/architecture\/refactoring\/multi.png?resize=269%2C197&#038;ssl=1\" width=\"269\" height=\"197\" data-recalc-dims=\"1\" \/><\/p>\n<p>Figure 2: Multiple clients, and multiple entry points, shows how a range of clients may interact with a shared component through many entry points. This is the difficult scenario, and the following tasks must be executed:<\/p>\n<ol>\n<li>Determine the entry points (could be done programmatically by the linker, i.e., remove the legacy code objects from the linker options).<\/li>\n<li>Decide between the following solutions:\n<ol>\n<li>Decide if the entry points in the legacy code are close enough to be moved to a common location (perhaps even a common class).<\/li>\n<li>If the gap between the entry points is too large, determine the possible side-effects of modifying the underlying code for the entry points, and isolate the separate interface.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>A primitive example of case 2.a could be a set of free functions for string operations, where the implementation is spread across the code base. Moving the interface and implementation to a common location introduces a common interface available to the entry points. However, it also introduces the possibility to modify the underlying code in a central place while keeping the interface intact.<\/p>\n<p>An example of case 2.b could be a set of free functions for string operations and a set of free functions for database access. These are logically too wide apart, and would ideally be split up in two separate interfaces.<\/p>\n<p>Having identified the entry points and interfaces to the legacy code, we should reconsider the interface and possibly update it. It makes perfect sense to introduce incremental &#8220;face lifts&#8221; in the source code, i.e., refactor once in a while to keep them in sync with their usage. In the example of case 2.b, it may not be possible to separate the two chunks, and thus an adapter might come in handy.<\/p>\n<h2>Adding the new feature<\/h2>\n<p>Having the legacy code and its interfaces prepared for the new feature, we will now have a look at how the feature could be introduced.<\/p>\n<p><img loading=\"lazy\" src=\"https:\/\/i1.wp.com\/www.codeproject.com\/KB\/architecture\/refactoring\/feature.png?resize=235%2C270&#038;ssl=1\" width=\"235\" height=\"270\" data-recalc-dims=\"1\" \/><\/p>\n<p>The above figure shows an UML diagram of the expected structure. The Common Interface is the interface entry point introduced in the previous section of this article. To abstract the code beneath this point, we introduce an adapter, interpreting the common interface and handling requests to the underlying implementation. The adapter holds references or instances of the legacy code and the new feature code. The mechanism for alternating between the legacy code and the new feature code is placed in the adapter. It may be necessary to extend the existing data structures to keep information about its origin, i.e., if the value originates from legacy code or new feature code.<\/p>\n<h3>Code before:<\/h3>\n<pre id=\"pre966471\" class=\"notranslate\" lang=\"cs\">typedef <span class=\"code-keyword\">struct<\/span>  \r\n{\r\n  <span class=\"code-keyword\">char<\/span> *text;\r\n  size_t length;\r\n} data_t;\r\n\r\n<span class=\"code-keyword\">void<\/span> str_analyze(data_t *data)\r\n{\r\n  <span class=\"code-summarycomment\">\/\/\/<\/span><span class=\"code-comment\"> Put code here\r\n<\/span>}<\/pre>\n<h3>Code after<\/h3>\n<pre id=\"pre847499\" class=\"notranslate\" lang=\"cs\">typedef <span class=\"code-keyword\">struct<\/span>  \r\n{\r\n  <span class=\"code-keyword\">char<\/span> *text;\r\n  size_t length;\r\n  unsigned <span class=\"code-keyword\">char<\/span> origin;\r\n} data_t;\r\n\r\n<span class=\"code-keyword\">void<\/span> str_analyze(data_t *data)\r\n{\r\n  <span class=\"code-keyword\">switch<\/span> (data-&gt;origin)\r\n  {\r\n  <span class=\"code-keyword\">case<\/span> LEGACY: \r\n    str_analyze_old(data);\r\n    <span class=\"code-keyword\">break<\/span>;\r\n  <span class=\"code-keyword\">case<\/span> FEATURE:\r\n    str_analyze_new(data);\r\n    <span class=\"code-keyword\">break<\/span>\r\n  }\r\n}<\/pre>\n<p>The previous code samples illustrate how the alternating adapter could be added to handle legacy code along side with new feature code. Note that the data structure has been updated with an\u00a0<code>origin<\/code>\u00a0variable, and that the function retains its original interface. Here, the function &#8220;<code>str_analyze<\/code>&#8221; acts as an adapter, as it translates incoming requests, but also as a facade since it is also in charge of delegating the work. The adapter is run time datadriven and enables the feature depending on context.<\/p>\n<h2>What if &#8230;<\/h2>\n<p>What if not all the legacy code should be updated for the newly added feature? Working with a large legacy code base, we are bound to have many generic functions, i.e., reading contents of file to string or similar common functions.<\/p>\n<p><img loading=\"lazy\" src=\"https:\/\/i1.wp.com\/www.codeproject.com\/KB\/architecture\/refactoring\/whatif.png?resize=257%2C270&#038;ssl=1\" width=\"257\" height=\"270\" data-recalc-dims=\"1\" \/><\/p>\n<p>Figure 4: In the previous section, we introduced an adapter layer to handle incoming requests. Modifying this as shown in the above figure gives the code direct access to the legacy code while still keeping the code open for future implementations. This is illustrated in the code samples below.<\/p>\n<h3>Code before:<\/h3>\n<pre id=\"pre377820\" class=\"notranslate\" lang=\"cs\">typedef <span class=\"code-keyword\">struct<\/span>  \r\n{\r\n  <span class=\"code-keyword\">char<\/span> *text;\r\n  size_t length;\r\n} data_t;\r\n\r\ndata_t * str_readf(<span class=\"code-keyword\">const<\/span> char* filename)\r\n{\r\n  <span class=\"code-summarycomment\">\/\/\/<\/span><span class=\"code-comment\"> Put code here\r\n<\/span>  <span class=\"code-keyword\">return<\/span> data;\r\n}<\/pre>\n<h3>Code after:<\/h3>\n<pre id=\"pre714004\" class=\"notranslate\" lang=\"cs\">typedef <span class=\"code-keyword\">struct<\/span>  \r\n{\r\n  <span class=\"code-keyword\">char<\/span> *text;\r\n  size_t length;\r\n  unsigned <span class=\"code-keyword\">char<\/span> origin;\r\n} data_t;\r\n\r\ndata_t * str_readf(<span class=\"code-keyword\">const<\/span> char* filename)\r\n{\r\n  <span class=\"code-keyword\">return<\/span> str_readf_old(filename);\r\n}<\/pre>\n<h2>In closing<\/h2>\n<p>To put it short, this article provides a small example of how to extend existing code bases with new and shiny features. Working with commercial code, we are often met with the challenge of implementing a new feature in very old and very messy legacy code bases. The code is most likely written in an era without emphasis on Design Patterns and maintainability. Following the simple guides from this article, it should be possible to seamlessly extend legacy code bases without tampering with existing functionality. Using the method described in this article, we will have to deal with the following issues:<\/p>\n<ul>\n<li><strong>Maintainability<\/strong>: Updating or modifying either the legacy code base or the new feature code is possible without tampering the other.<\/li>\n<li><strong>Testability<\/strong>: Introducing the Adapter and Facade patterns imposes a layer of abstraction, making it possible to test the underlying code with unit tests.<\/li>\n<li><strong>Flexibility<\/strong>: The Facade pattern allows the developer to change the underlying code, infrastructure, etc., without changing the interface.<\/li>\n<li><strong>Feature Toggling<\/strong>: Allowing specific features to be visible\u00a0for selected users or context<\/li>\n<\/ul>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Back in 2007 I wrote an article on how to\u00a0prepare your code for refactoring without tampering with legacy code that needs to remain intact. Recently I have found that this\u00a0design pattern may be useful for&#8230;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":529,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[3,21],"tags":[5,85,6],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v17.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Feature Toggles - @agilerasmus<\/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:\/\/agilerasmus.com\/wordpress\/feature-toggles\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Feature Toggles - @agilerasmus\" \/>\n<meta property=\"og:description\" content=\"Back in 2007 I wrote an article on how to\u00a0prepare your code for refactoring without tampering with legacy code that needs to remain intact. Recently I have found that this\u00a0design pattern may be useful for...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/\" \/>\n<meta property=\"og:site_name\" content=\"@agilerasmus\" \/>\n<meta property=\"article:published_time\" content=\"2017-10-28T09:14:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i1.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/10\/Mh_eisenbahnweiche_mit_handhebel.jpeg?fit=777%2C455&#038;ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"777\" \/>\n\t<meta property=\"og:image:height\" content=\"455\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/#website\",\"url\":\"https:\/\/agilerasmus.com\/wordpress\/\",\"name\":\"@agilerasmus\",\"description\":\"agile coach, trainer and scrum master\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/agilerasmus.com\/wordpress\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-GB\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#primaryimage\",\"inLanguage\":\"en-GB\",\"url\":\"https:\/\/i1.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/10\/Mh_eisenbahnweiche_mit_handhebel.jpeg?fit=777%2C455&ssl=1\",\"contentUrl\":\"https:\/\/i1.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/10\/Mh_eisenbahnweiche_mit_handhebel.jpeg?fit=777%2C455&ssl=1\",\"width\":777,\"height\":455},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#webpage\",\"url\":\"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/\",\"name\":\"Feature Toggles - @agilerasmus\",\"isPartOf\":{\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#primaryimage\"},\"datePublished\":\"2017-10-28T09:14:48+00:00\",\"dateModified\":\"2017-10-28T09:14:48+00:00\",\"author\":{\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/#\/schema\/person\/cc0de41731dfcf8697fd64dadadcf096\"},\"breadcrumb\":{\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/agilerasmus.com\/wordpress\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Feature Toggles\"}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/#\/schema\/person\/cc0de41731dfcf8697fd64dadadcf096\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/agilerasmus.com\/wordpress\/#personlogo\",\"inLanguage\":\"en-GB\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/024753e28bdb374a97740a4d5572755e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/024753e28bdb374a97740a4d5572755e?s=96&d=mm&r=g\",\"caption\":\"admin\"},\"url\":\"https:\/\/agilerasmus.com\/wordpress\/author\/admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Feature Toggles - @agilerasmus","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:\/\/agilerasmus.com\/wordpress\/feature-toggles\/","og_locale":"en_GB","og_type":"article","og_title":"Feature Toggles - @agilerasmus","og_description":"Back in 2007 I wrote an article on how to\u00a0prepare your code for refactoring without tampering with legacy code that needs to remain intact. Recently I have found that this\u00a0design pattern may be useful for...","og_url":"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/","og_site_name":"@agilerasmus","article_published_time":"2017-10-28T09:14:48+00:00","og_image":[{"width":777,"height":455,"url":"https:\/\/i1.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/10\/Mh_eisenbahnweiche_mit_handhebel.jpeg?fit=777%2C455&ssl=1","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Written by":"admin","Estimated reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebSite","@id":"https:\/\/agilerasmus.com\/wordpress\/#website","url":"https:\/\/agilerasmus.com\/wordpress\/","name":"@agilerasmus","description":"agile coach, trainer and scrum master","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/agilerasmus.com\/wordpress\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-GB"},{"@type":"ImageObject","@id":"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#primaryimage","inLanguage":"en-GB","url":"https:\/\/i1.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/10\/Mh_eisenbahnweiche_mit_handhebel.jpeg?fit=777%2C455&ssl=1","contentUrl":"https:\/\/i1.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/10\/Mh_eisenbahnweiche_mit_handhebel.jpeg?fit=777%2C455&ssl=1","width":777,"height":455},{"@type":"WebPage","@id":"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#webpage","url":"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/","name":"Feature Toggles - @agilerasmus","isPartOf":{"@id":"https:\/\/agilerasmus.com\/wordpress\/#website"},"primaryImageOfPage":{"@id":"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#primaryimage"},"datePublished":"2017-10-28T09:14:48+00:00","dateModified":"2017-10-28T09:14:48+00:00","author":{"@id":"https:\/\/agilerasmus.com\/wordpress\/#\/schema\/person\/cc0de41731dfcf8697fd64dadadcf096"},"breadcrumb":{"@id":"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/agilerasmus.com\/wordpress\/feature-toggles\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/agilerasmus.com\/wordpress\/"},{"@type":"ListItem","position":2,"name":"Feature Toggles"}]},{"@type":"Person","@id":"https:\/\/agilerasmus.com\/wordpress\/#\/schema\/person\/cc0de41731dfcf8697fd64dadadcf096","name":"admin","image":{"@type":"ImageObject","@id":"https:\/\/agilerasmus.com\/wordpress\/#personlogo","inLanguage":"en-GB","url":"https:\/\/secure.gravatar.com\/avatar\/024753e28bdb374a97740a4d5572755e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/024753e28bdb374a97740a4d5572755e?s=96&d=mm&r=g","caption":"admin"},"url":"https:\/\/agilerasmus.com\/wordpress\/author\/admin\/"}]}},"jetpack_featured_media_url":"https:\/\/i1.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/10\/Mh_eisenbahnweiche_mit_handhebel.jpeg?fit=777%2C455&ssl=1","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8dzln-8t","jetpack-related-posts":[{"id":101,"url":"https:\/\/agilerasmus.com\/wordpress\/about-the-author\/","url_meta":{"origin":525,"position":0},"title":"About Rasmus Kaae","date":"December 18, 2015","format":false,"excerpt":"Rasmus is certified SAFe Program Consultant, Agile Leader, Scrum Master, Scrum Product Owner and Scrum Professional. Rasmus is dedicated to bring Scrum, Kanban and agility into organisations by having a full stack end-to-end and top-to-bottom approach. As a trainer, Rasmus brings his professional experience from coaching and training more than\u2026","rel":"","context":"In &quot;About&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2015\/12\/rasmus.jpeg?fit=1024%2C768&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":556,"url":"https:\/\/agilerasmus.com\/wordpress\/scrum-as-a-process-bus\/","url_meta":{"origin":525,"position":1},"title":"Scrum as a process bus","date":"May 27, 2018","format":false,"excerpt":"Many organisations are rapidly taking Scrum as their core agile framework - this is positive in many ways. The framework is an industry standard that is taught at universities and IT colleges. But there is a big and comon pitfall - an anti-pattern that should be avoided: Scrum is tailored\u2026","rel":"","context":"In &quot;English&quot;","img":{"alt_text":"","src":"https:\/\/i2.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/11\/main-board-89050_960_720.jpg?fit=960%2C690&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":55,"url":"https:\/\/agilerasmus.com\/wordpress\/doing-scrum-or-being-agile\/","url_meta":{"origin":525,"position":2},"title":"Doing Scrum or being agile?","date":"September 11, 2014","format":false,"excerpt":"Did you know that it is possible to perform Scrum without being Agile - and being Agile is not about following Scrum?I recently participated in a discussion about the differences between the two concepts: Agile and Scrum. Many falsely assume that they are Agile simply due to the fact that\u2026","rel":"","context":"In &quot;English&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2016\/12\/img_4432.jpg?fit=374%2C562&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":564,"url":"https:\/\/agilerasmus.com\/wordpress\/handling-dependencies-with-nexus\/","url_meta":{"origin":525,"position":3},"title":"Nexus exoskeleton","date":"November 22, 2017","format":false,"excerpt":"One of the trending buzz-words within agile software development is \u201cscaling\u201d. This has been discovered by the gurus within agile processes and we currently see heaps of frameworks popping up. Each of these frameworks pose a solution to scaling work across several teams. But what does scaling actually mean and\u2026","rel":"","context":"In &quot;English&quot;","img":{"alt_text":"","src":"https:\/\/i2.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/11\/workplace-1245776_960_720.jpg?fit=960%2C640&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1049,"url":"https:\/\/agilerasmus.com\/wordpress\/relationship-between-agile-and-scrum\/","url_meta":{"origin":525,"position":4},"title":"Relationship Between Agile and Scrum","date":"June 23, 2021","format":false,"excerpt":"Did you know that it is possible to perform Scrum without being Agile \u2013 and being Agile is not about following Scrum? \u00a0Many falsely assume that they are Agile simply since they perform Scrum in their daily work. It\u2019s a basic assumption, which may have consequences to the success of\u2026","rel":"","context":"In &quot;English&quot;","img":{"alt_text":"","src":"https:\/\/i1.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2021\/06\/hands-1917895_1280.png?fit=1200%2C900&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":454,"url":"https:\/\/agilerasmus.com\/wordpress\/what-happens-after-scrum\/","url_meta":{"origin":525,"position":5},"title":"What happens after Scrum?","date":"June 3, 2017","format":false,"excerpt":"\u00a0 At Scrumday 2017 held in Simcorp I presented parts of the work that I have been involved in and the thoughts that follows an agile transformation. On a personal level \u2013 the journey with Bankdata already started back at Scrumday 2016 where my colleague Claus gave a talk on\u2026","rel":"","context":"In &quot;English&quot;","img":{"alt_text":"","src":"https:\/\/i2.wp.com\/agilerasmus.com\/wordpress\/wp-content\/uploads\/2017\/06\/Slide1.png?fit=960%2C540&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/posts\/525"}],"collection":[{"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/comments?post=525"}],"version-history":[{"count":3,"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/posts\/525\/revisions"}],"predecessor-version":[{"id":530,"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/posts\/525\/revisions\/530"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/media\/529"}],"wp:attachment":[{"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/media?parent=525"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/categories?post=525"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/agilerasmus.com\/wordpress\/wp-json\/wp\/v2\/tags?post=525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}