<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jeroen De Dauw</title>
    <description>The latest articles on Forem by Jeroen De Dauw (@jeroendedauw).</description>
    <link>https://forem.com/jeroendedauw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2884%2F27097c7514e0bf985ccbe9a8ccd2a550.jpeg</url>
      <title>Forem: Jeroen De Dauw</title>
      <link>https://forem.com/jeroendedauw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jeroendedauw"/>
    <language>en</language>
    <item>
      <title>Clean Comparisons</title>
      <dc:creator>Jeroen De Dauw</dc:creator>
      <pubDate>Mon, 18 Sep 2023 08:42:00 +0000</pubDate>
      <link>https://forem.com/jeroendedauw/readable-comparisons-2f4o</link>
      <guid>https://forem.com/jeroendedauw/readable-comparisons-2f4o</guid>
      <description>&lt;p&gt;In programming, readability is just as crucial as functionality. One area that often gets overlooked is the way we write comparisons. Using ambiguous comparisons can make your code harder to understand and lead to unexpected bugs. In this post, we'll look at how to make your comparisons in PHP and JavaScript both readable and reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Readable PHP Comparisons
&lt;/h2&gt;

&lt;p&gt;Beyond being a dynamic language, PHP has some weird and unexpected behavior when casting values. For instance, if you have a string with a zero, it will evaluate to false if you do &lt;code&gt;!$string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, in PHP, you are incentivized to do explicit comparisons not just for readability but also for correctness.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Ambiguous form&lt;/th&gt;
&lt;th&gt;Clear replacement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Is array empty?&lt;/td&gt;
&lt;td&gt;!$list&lt;/td&gt;
&lt;td&gt;$list === []&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is array empty?&lt;/td&gt;
&lt;td&gt;empty($list)&lt;/td&gt;
&lt;td&gt;$list === []&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is string empty?&lt;/td&gt;
&lt;td&gt;!$string&lt;/td&gt;
&lt;td&gt;$string === ''&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is int zero?&lt;/td&gt;
&lt;td&gt;!$int&lt;/td&gt;
&lt;td&gt;$int === 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is null?&lt;/td&gt;
&lt;td&gt;!$typeOrNull&lt;/td&gt;
&lt;td&gt;$typeOrNull === null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalar equals?&lt;/td&gt;
&lt;td&gt;$a == $b&lt;/td&gt;
&lt;td&gt;$a === $b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Array key exists?&lt;/td&gt;
&lt;td&gt;isset($list[$a])&lt;/td&gt;
&lt;td&gt;array_key_exists($a, $list)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is null or false?&lt;/td&gt;
&lt;td&gt;!$mixed&lt;/td&gt;
&lt;td&gt;$mixed === null || $mixed === false&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Readable JavaScript Comparisons
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Ambiguous form&lt;/th&gt;
&lt;th&gt;Clear replacement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Is array empty?&lt;/td&gt;
&lt;td&gt;!arr.length&lt;/td&gt;
&lt;td&gt;arr.length === 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is string empty?&lt;/td&gt;
&lt;td&gt;!str&lt;/td&gt;
&lt;td&gt;str === ''&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is number zero?&lt;/td&gt;
&lt;td&gt;!num&lt;/td&gt;
&lt;td&gt;num === 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is null?&lt;/td&gt;
&lt;td&gt;!val&lt;/td&gt;
&lt;td&gt;val === null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is equal?&lt;/td&gt;
&lt;td&gt;a == b&lt;/td&gt;
&lt;td&gt;a === b&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  More Comparisons
&lt;/h2&gt;

&lt;p&gt;What did I miss? Do you disagree with any of the above? Let me know in the comments!&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>programming</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Advice for Junior Developers</title>
      <dc:creator>Jeroen De Dauw</dc:creator>
      <pubDate>Tue, 11 Oct 2022 12:11:33 +0000</pubDate>
      <link>https://forem.com/jeroendedauw/advice-for-junior-developers-30am</link>
      <guid>https://forem.com/jeroendedauw/advice-for-junior-developers-30am</guid>
      <description>&lt;p&gt;Over the 15+ years of my development career, I have learned several things that significantly increase my effectiveness. In this post, I share those learnings with you.&lt;/p&gt;

&lt;p&gt;Structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Foundational Advice -- Important context and motivation for what follows&lt;/li&gt;
&lt;li&gt;Technical Advice -- The main course&lt;/li&gt;
&lt;li&gt;Recommended Reading -- Links to high-quality books and blogs that are great for getting started&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This blog post mentions and links valuable concepts that you can explore further as you see fit.&lt;/p&gt;

&lt;h2&gt;Foundational Advice for Juniors&lt;/h2&gt;

&lt;h3&gt;1. Code is not the Point&lt;/h3&gt;

&lt;p&gt;As developers, we like writing code. Most of us want to be given a nice unambiguous task. A fun technical puzzle to solve without paying attention to the rest of the world.&lt;/p&gt;

&lt;p&gt;Put reasonable effort into making sure that you are solving the right problem. To quote Peter Drucker: &lt;a href="https://medium.com/swlh/there-is-nothing-so-useless-as-doing-efficiently-something-that-should-not-have-been-done-at-all-8c5d2282319d" rel="noopener noreferrer"&gt;There is nothing so useless as doing efficiently that which should not be done at all&lt;/a&gt;. Gather feedback early and often, typically by continuous delivery to real users. &lt;a href="https://agilemanifesto.org/" rel="noopener noreferrer"&gt;Be&lt;/a&gt; &lt;a href="https://agilemanifesto.org/principles.html" rel="noopener noreferrer"&gt;Agile&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Software development is expensive, with the vast majority of the effort of real-world projects typically going into maintenance. Combine this with the goal being user/business outcomes, &lt;a href="https://blog.codinghorror.com/the-best-code-is-no-code-at-all/" rel="noopener noreferrer"&gt;the best code is often no code&lt;/a&gt;. To quote Bill Gates: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight."&lt;/p&gt;

&lt;p&gt;See also: &lt;a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it" rel="noopener noreferrer"&gt;YAGNI&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/KISS_principle" rel="noopener noreferrer"&gt;KISS&lt;/a&gt;, &lt;a href="https://blog.codinghorror.com/the-last-responsible-moment/" rel="noopener noreferrer"&gt;The Last Responsible Moment&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;2. Software Design Matters&lt;/h3&gt;

&lt;p&gt;During the first 5 years of my development career, I thought that software design is for software architects or other people with special roles. I was focused on "getting things done", and saw software design and practices such as writing tests, as a distraction at best. My code worked, and I was getting a lot of things done. Or so I thought.&lt;/p&gt;

&lt;p&gt;Then I read &lt;a href="https://www.goodreads.com/book/show/3735293-clean-code" rel="noopener noreferrer"&gt;Clean Code&lt;/a&gt;, by &lt;a href="https://cleancoders.com/" rel="noopener noreferrer"&gt;Robert C. Martin&lt;/a&gt;. This book motivates caring about software design and contains examples and many technical heuristics. The central takeaway of the book is: "&lt;strong&gt;The only way to go fast is to go well&lt;/strong&gt;". In other words, &lt;a href="https://martinfowler.com/articles/is-quality-worth-cost.html" rel="noopener noreferrer"&gt;if you make a mess, it will slow you down&lt;/a&gt;. See also: &lt;a href="https://martinfowler.com/bliki/TradableQualityHypothesis.html" rel="noopener noreferrer"&gt;TradableQualityHypothesis&lt;/a&gt;, &lt;a href="https://martinfowler.com/bliki/DesignStaminaHypothesis.html" rel="noopener noreferrer"&gt;DesignStaminaHypothesis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learning how to write well-designed clean code of course takes time and effort. And when you start, you will be slower and make mistakes. &lt;a href="https://www.entropywins.wtf/blog/2017/01/02/simple-is-not-easy/" rel="noopener noreferrer"&gt;Simple is not Easy&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;3. Use the BEST Practices&lt;/h3&gt;

&lt;p&gt;Writing tests tends to be beneficial. There are exceptions, but most of the time, it makes a lot of sense to write automated tests. Writing tests is an example of a best practice.&lt;/p&gt;

&lt;p&gt;If you are new to writing tests, just follow the best practice and write tests for everything. &lt;strong&gt;When starting, blindly following the best practice will be better than following your own underdeveloped judgment&lt;/strong&gt;. Over time you will learn how to write tests effectively, and be able to tell the difference between you have messed up, and situations where writing a test is not worth it. You will also start to understand the value tests bring on a more visceral level, by having experienced the decrease in debugging sessions and the worry-free refactoring enabled by your tests. &lt;strong&gt;After developing your judgment, you will be able to transcend the best practice&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This advice applies to best practices in any area that you are a junior in. Automated tests are just an example.&lt;/p&gt;

&lt;p&gt;One big gotcha is that it is not easy to tell the difference between a sensible best practice and something nonsensical or even counterproductive. This is made more complicated by most existing code being a mess, and by most developers, including "experienced" and "senior" ones, not knowing software design basics. This makes having a good mentor extremely valuable. Barring that, one piece of advice based on my own experiences is to be wary of best practices specific to the community of your language or framework. Look for evergreen advice that has been around for decades.&lt;/p&gt;

&lt;h2&gt;Technical Advice for Juniors&lt;/h2&gt;

&lt;p&gt;Our focus will be on technical topics. Many other areas are important, such as health, happiness, career, and soft skills. Knowing how to avoid a technical pitfall won't help you if you are sleep deprived and working on the wrong problem for a toxic boss that underpays you.&lt;/p&gt;

&lt;h3&gt;4. Write Tests&lt;/h3&gt;

&lt;p&gt;Write automated tests. Perhaps write tests before the code, such as via &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development" rel="noopener noreferrer"&gt;Test Driven Development&lt;/a&gt; (TDD). This makes it easy to verify your code is correct in a repeatable manner, thus saving you from much manual retresting and from debugging sessions.&lt;/p&gt;

&lt;blockquote&gt;You think test-first is difficult? Try debug-after.&lt;/blockquote&gt;

&lt;p&gt;Perhaps even more importantly, tests give you the safety net to refactor your code. And continuous refactoring is needed to keep your code clean. Without a reliable test suite, it is all the more likely that your code will rot.&lt;/p&gt;

&lt;p&gt;Writing tests is difficult if the design of your code is poor, such as when using inheritance for code reuse, or when using static functions. If on the other hand, you have &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt; classes, with no global dependencies, then writing nice tests is not so difficult.&lt;/p&gt;

&lt;p&gt;Test design matters because poorly written tests will slow you down. Avoid binding your tests to implementation details of the code under test or to the structure of the system. Avoid overusing Mocks and &lt;a href="https://www.entropywins.wtf/blog/2016/05/13/5-ways-to-write-better-mocks/" rel="noopener noreferrer"&gt;write better Test Doubles&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;5. Do Not Use Inheritance For Code Reuse&lt;/h3&gt;

&lt;p&gt;This is one of those best practices that bring to mind the "Use the Best Practices" section. My advice: do not use inheritance for code reuse at all when you are starting out. It is rarely the right call and can do a lot of harm. &lt;a href="https://en.wikipedia.org/wiki/Composition_over_inheritance" rel="noopener noreferrer"&gt;Favor composition over inheritance&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;6. Write Object-Oriented code&lt;/h3&gt;

&lt;p&gt;Write &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt; code that is not &lt;a href="https://williamdurand.fr/2013/07/30/from-stupid-to-solid-code/" rel="noopener noreferrer"&gt;STUPID&lt;/a&gt;. There is so much value in understanding these principles and anti-patterns.&lt;/p&gt;

&lt;p&gt;Actually create objects. Classes with only static methods are not OO. Try to avoid using static code altogether.&lt;/p&gt;

&lt;p&gt;See also: &lt;a href="https://www.entropywins.wtf/blog/2017/02/17/why-every-single-argument-of-dan-north-is-wrong/" rel="noopener noreferrer"&gt;my defense of SOLID&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;7. Write Functional Code&lt;/h3&gt;

&lt;p&gt;(&lt;a href="https://en.wikipedia.org/wiki/Functional_programming" rel="noopener noreferrer"&gt;Functional programming&lt;/a&gt; is not to be confused with &lt;a href="https://en.wikipedia.org/wiki/Imperative_programming" rel="noopener noreferrer"&gt;imperative&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Structured_programming" rel="noopener noreferrer"&gt;structural programming&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;This point is not about fully switching to a functional language. You can benefit from using a functional style in your OO language. &lt;a href="https://www.entropywins.wtf/blog/2018/10/24/readable-functions-minimize-state/" rel="noopener noreferrer"&gt;Minimize state&lt;/a&gt;, especially mutable state, and &lt;a href="https://www.entropywins.wtf/blog/2018/10/30/readable-functions-do-one-thing/" rel="noopener noreferrer"&gt;do one thing in your functions&lt;/a&gt;. See also: &lt;a href="https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell" rel="noopener noreferrer"&gt;functional core, imperative shell&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;8. Use Informed Duplication&lt;/h3&gt;

&lt;p&gt;Copy-pasting big chunks of code to multiple places is almost always unwise. Any self-respecting developer soon learns this and starts to follow some form of &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;Don't Repeat Yourself&lt;/a&gt; (DRY). Unfortunately, the well-intended pursuit of DRY often leads to overengineering and accidental complexity. This is where the counterpart of DRY comes in: Write Everything Twice (WET). The idea behind WET is to only deduplicate on the third occurrence of duplication.&lt;/p&gt;

&lt;p&gt;For a more in-depth look at the costs and benefits of deduplication, see &lt;a href="https://www.entropywins.wtf/blog/2017/09/06/the-fallacy-of-dry/" rel="noopener noreferrer"&gt;The Fallacy of DRY&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;9. Types, Names and Comments&lt;/h3&gt;

&lt;p&gt;Try to write self-documenting code and avoid comments.&lt;/p&gt;

&lt;blockquote&gt;Every time you write a comment, you should grimace and feel the failure of your ability of expression. -- Robert C. Martin&lt;/blockquote&gt;

&lt;p&gt;Comments are dangerous because they can lie. The code can change without the comment being updated. New code can be added right under the comment. The comment might have been wrong or inaccurate in the first place. When this happens, the comment not only becomes useless, it becomes misleading.&lt;/p&gt;

&lt;p&gt;To write self-documenting code:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://www.entropywins.wtf/blog/2018/10/30/readable-functions-do-one-thing/" rel="noopener noreferrer"&gt;Do one thing in your functions&lt;/a&gt;
&lt;ul&gt;
    &lt;li&gt;By doing a single thing in a function, you can give it a clear name&lt;/li&gt;
    &lt;li&gt;Feel the need to explain what different sections of your function do by adding comments? Instead, extract each section into its own well-named function.&lt;/li&gt;
    &lt;li&gt;"&lt;a href="https://verraes.net/2013/09/extract-till-you-drop/" rel="noopener noreferrer"&gt;Extract till you drop&lt;/a&gt;": if you can meaningfully extract a function, then you probably should. Don't be afraid of small functions.&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://martinfowler.com/bliki/CommandQuerySeparation.html" rel="noopener noreferrer"&gt;Command Query Separation&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Similar to the &lt;a href="https://en.wikipedia.org/wiki/Single-responsibility_principle" rel="noopener noreferrer"&gt;Single Responsibility Principle&lt;/a&gt; for classes (The S in SOLID)&lt;/li&gt;
&lt;/ul&gt;




&lt;/li&gt;


    &lt;li&gt;&lt;a href="https://www.entropywins.wtf/blog/2018/10/24/readable-functions-minimize-state/" rel="noopener noreferrer"&gt;&lt;strong&gt;Minimize state&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;


    &lt;li&gt;

&lt;strong&gt;Use types&lt;/strong&gt;. Combined with a test suite that executes the code, you can rely on the types telling the truth.&lt;/li&gt;


    &lt;li&gt;

&lt;strong&gt;Avoid mixed types&lt;/strong&gt;. Avoid parameters or return values that can be an integer, a boolean, or a string. This naturally happens if you write focused functions that only do one thing.&lt;/li&gt;


    &lt;li&gt;

&lt;strong&gt;Write tests&lt;/strong&gt;. A well-written and comprehensive test suite shows you how the production code can be used, and how it behaves.&lt;/li&gt;


&lt;/ul&gt;

&lt;p&gt;
&lt;a href="https://www.goodreads.com/book/show/3735293-clean-code" rel="noopener noreferrer"&gt;Clean Code&lt;/a&gt; by Robert C. Martin has some good rules of thumb about naming and comments.
&lt;/p&gt;

&lt;h2&gt;Recommended Reading for Juniors&lt;/h2&gt;

&lt;h3&gt;Books&lt;/h3&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;&lt;a href="https://www.goodreads.com/book/show/3735293-clean-code" rel="noopener noreferrer"&gt;Clean Code&lt;/a&gt;, 2007 book by Robert C. Martin&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;a href="https://www.goodreads.com/book/show/5608045-apprenticeship-patterns" rel="noopener noreferrer"&gt;Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman&lt;/a&gt;, 2009 book&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/44919.Working_Effectively_with_Legacy_Code" rel="noopener noreferrer"&gt;Working Effectively with Legacy Code&lt;/a&gt;, 2004 book by Michael Feathers&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/44936.Refactoring" rel="noopener noreferrer"&gt;Refactoring: Improving the Design of Existing Code&lt;/a&gt;, 1999 book&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://www.goodreads.com/book/show/23215733-the-software-craftsman" rel="noopener noreferrer"&gt;The Software Craftsman&lt;/a&gt;, 2014 book&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Blogs&lt;/h3&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://martinfowler.com/" rel="noopener noreferrer"&gt;MartinFowler.com&lt;/a&gt; - Tons of high-quality articles about all things software development&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://www.entropywins.wtf" rel="noopener noreferrer"&gt;EntropyWins.wtf&lt;/a&gt; - Clearly the best blog on the internet :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See also: &lt;a href="https://blog.codinghorror.com/recommended-reading-for-developers/" rel="noopener noreferrer"&gt;Recommended Reading for Developers&lt;/a&gt; by Jeff Atwood&lt;/p&gt;

&lt;h2&gt;Bonus links&lt;/h2&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://martinfowler.com/bliki/TellDontAsk.html" rel="noopener noreferrer"&gt;Tell Don't Ask&lt;/a&gt; -- Encapsulation best practice&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://wiki.c2.com/?LawOfDemeter" rel="noopener noreferrer"&gt;Law of Demeter&lt;/a&gt; -- Coupling best practice&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Domain-driven_design" rel="noopener noreferrer"&gt;Domain Driven Design&lt;/a&gt; -- A sizeable toolbox. More advanced, good to first learn the basics.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://williamdurand.fr/2013/06/03/object-calisthenics/" rel="noopener noreferrer"&gt;Object Calisthenics&lt;/a&gt; -- Rules that restrict what you can do in programming. Nice for learning how to do things differently&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Pair_programming" rel="noopener noreferrer"&gt;Pair Programming&lt;/a&gt; -- A great way to learn from each other&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://codingdojo.org/kata/" rel="noopener noreferrer"&gt;Code katas&lt;/a&gt; -- Simple programming, great for practicing a specific technique or skill such as Test Driven Development&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;About Jeroen&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.entropywins.wtf/" rel="noopener noreferrer"&gt;Jeroen De Dauw&lt;/a&gt; is CEO of &lt;a href="https://professional.wiki/" rel="noopener noreferrer"&gt;Professional Wiki&lt;/a&gt;, which provides &lt;a href="https://www.pro.wiki/" rel="noopener noreferrer"&gt;wiki hosting&lt;/a&gt; services. He occasionally writes on his &lt;a href="https://www.entropywins.wtf/blog/" rel="noopener noreferrer"&gt;software design blog&lt;/a&gt;. You can &lt;a href="https://twitter.com/JeroenDeDauw" rel="noopener noreferrer"&gt;follow Jeroen on Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>productivity</category>
      <category>codenewbie</category>
      <category>learning</category>
    </item>
    <item>
      <title>Applications as Frameworks</title>
      <dc:creator>Jeroen De Dauw</dc:creator>
      <pubDate>Mon, 04 Mar 2019 07:04:25 +0000</pubDate>
      <link>https://forem.com/jeroendedauw/applications-as-frameworks-j1f</link>
      <guid>https://forem.com/jeroendedauw/applications-as-frameworks-j1f</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;Decoupled web application&lt;/h3&gt;

&lt;p&gt;In your typical web application, the code handles a request and returns a response. Let's assume we are using a web framework to handle common tasks such as routing. Let's also assume that we think framework binding has a high cost and decouple our application from it. The flow of control would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyb5k97qdh4bxyrq8puw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyb5k97qdh4bxyrq8puw.png" alt="Diagram" width="438" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Execution starts with the framework. For PHP frameworks this will be in a file like &lt;code&gt;public/index.php&lt;/code&gt;. The framework then bootstraps itself and does a bunch of stuff. It's safe to assume this stuff will include routing, and often it also includes things like dependency construction and error handling.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftb08shiqqug7frz3ncqj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftb08shiqqug7frz3ncqj.png" alt="Diagram" width="438" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My post &lt;a href="https://www.entropywins.wtf/blog/2016/11/24/implementing-the-clean-architecture/" rel="noopener noreferrer"&gt;Implementing The Clean Architecture&lt;/a&gt; outlines one architectural approach that leads to this kind of application.&lt;/p&gt;

&lt;h3&gt;Frameworks vs Applications&lt;/h3&gt;

&lt;p&gt;Let's compare how frameworks and applications differ when they are used as a foundation for an/another application.&lt;/p&gt;

&lt;p&gt;Frameworks don'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'll need to deal with existing structure and behavior. You'll need to insert your own stuff, change existing behavior in certain situations and prevent default behavior altogether in others.&lt;/p&gt;

&lt;p&gt;I know that there are "frameworks" 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.&lt;/p&gt;

&lt;h3&gt;Plugins and Extensions&lt;/h3&gt;

&lt;p&gt;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 is in control over itself. And for extensions that use many extension points of the application yet are shallow/small, framework decoupling might not make sense.&lt;/p&gt;

&lt;p&gt;This post is about using applications as framework foundation for sizable sets of code which are applications in their own right.&lt;/p&gt;

&lt;h3&gt;Applications as Frameworks&lt;/h3&gt;

&lt;p&gt;Let's imagine we have an application that is used on some site for some use case. We'll call this application FrameworkApp, since we'll use it as framework for another application that powers another site.&lt;/p&gt;

&lt;p&gt;When building our application on top of FrameworkApp, we'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.&lt;/p&gt;

&lt;p&gt;This leads to a very different flow of control. Rather than calling us once, the FrameworkApp calls each extension point our application handles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzeu83fbn8ethbnskvip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzeu83fbn8ethbnskvip.png" alt="Diagram" width="438" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram is showing just 6 extension points, though there can be 100s.&lt;/p&gt;

&lt;p&gt;When visualized like this, it becomes easy to see how decoupling from the framework becomes next to impossible. Even if you manage to avoid coupling to framework &lt;em&gt;code&lt;/em&gt; in your application, its whole structure is still defined by the framework. 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.&lt;/p&gt;

&lt;h3&gt;An OOP Solution&lt;/h3&gt;

&lt;blockquote&gt;Favor composition over inheritance

&lt;small&gt;-- OOP principle&lt;/small&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using an application as a framework is very similar to using inheritance for code reuse.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://www.entropywins.wtf/blog/2017/09/06/the-fallacy-of-dry/" rel="noopener noreferrer"&gt;The Fallacy of DRY&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just like with class hierarchies you can always slap on an extra level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fl7qnupqy6xisktau3q3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fl7qnupqy6xisktau3q3a.png" alt="" width="663" height="280"&gt;&lt;/a&gt; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fg5rd2d20gjavwa7l15tg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fg5rd2d20gjavwa7l15tg.jpg" alt="" width="680" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://somehowimanage.blog/" rel="noopener noreferrer"&gt;Raz Shuty&lt;/a&gt; for proofreading and making some suggestions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.entropywins.wtf/blog/2019/02/28/applications-as-frameworks/" rel="noopener noreferrer"&gt;Applications as Frameworks&lt;/a&gt; was originally posted on &lt;a href="https://www.entropywins.wtf/blog" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;, where you can find many similar posts.&lt;/p&gt;

</description>
      <category>cleancode</category>
      <category>frameworks</category>
      <category>designpatterns</category>
      <category>antipatterns</category>
    </item>
    <item>
      <title>Base Libraries Should be Stable</title>
      <dc:creator>Jeroen De Dauw</dc:creator>
      <pubDate>Thu, 30 Aug 2018 16:20:35 +0000</pubDate>
      <link>https://forem.com/jeroendedauw/base-libraries-should-be-stable-2de5</link>
      <guid>https://forem.com/jeroendedauw/base-libraries-should-be-stable-2de5</guid>
      <description>&lt;p&gt;In this post I go over the principles that govern package (library) design and one specific issue I have come across several times.&lt;/p&gt;

&lt;p&gt;Robert C Martin has proposed &lt;a href="https://en.wikipedia.org/wiki/Package_principles" rel="noopener noreferrer"&gt;six Package Principles&lt;/a&gt;. Personally I find the (linked) description on Wikipedia rather confusing, especially if you do not already understand the principles. Here is my take on library design using short and simple points:&lt;/p&gt;

&lt;p&gt;Libraries should&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cover a single responsibility&lt;/li&gt;
&lt;li&gt;provide a clean and well segregated interface to their users&lt;/li&gt;
&lt;li&gt;hide/encapsulate implementation details&lt;/li&gt;
&lt;li&gt;not have cyclic dependencies&lt;/li&gt;
&lt;li&gt;not depend on less stable libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest of this post focuses on the importance of the last point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stable Base Libraries
&lt;/h2&gt;

&lt;p&gt;I am assuming usage of a package manager such as &lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt; (PHP) or NPM. This means that each library defines its dependencies (if any) and the version ranges of those that it is compatible with. Libraries have releases and these follow &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;semantic versioning&lt;/a&gt;. It also means that libraries are ultimately consumed by applications that define their dependencies in the same way.&lt;/p&gt;

&lt;p&gt;Consider the scenario where you have various applications that all consume a base library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1axe75k2j4tc5lxitk45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1axe75k2j4tc5lxitk45.png" alt="Diagram" width="586" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this library contains a lot of concrete code, it will not be very stable and it will now and then be needed or desired to make a major release. A major release is one that can contain breaking changes and therefore does not automatically get used by consumers of the library. These consumers instead need to manually update the version range of the library they are compatible with and possibly adjust their code to work with the breaking changes.&lt;/p&gt;

&lt;p&gt;In this scenario that is not a problem. Suppose the library is at version 1.2 and that all applications use version 1.x. If breaking changes are made in the library, these will need to be released as version 2.0. Due to the versioning system the consuming applications can upgrade at their leisure. There is of course some cost to making a major release. The consumers still do need to spend some time on the upgrade, especially if they are affected by the breaking changes. Still, this is typically easy to deal with and is a normal part of the development process.&lt;/p&gt;

&lt;p&gt;Things change drastically when we have an unstable library that is used by other libraries, even if those libraries themselves are unstable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmld54d9ccn6mvjansmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmld54d9ccn6mvjansmw.png" alt="Diagram" width="741" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In such a scenario making breaking changes to the base library are very costly. Let's assume we make a breaking change to the base library and that we want to use it in our application. What do we actually need to do to get there?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make a release of the base library (Library A)&lt;/li&gt;
&lt;li&gt;Update library B to specify it is compatible with the new version of A and make a new release of B&lt;/li&gt;
&lt;li&gt;Update library C to specify it is compatible with the new version of A and make a new release of C&lt;/li&gt;
&lt;li&gt;Update library D to specify it is compatible with the new version of A and make a new release of D&lt;/li&gt;
&lt;li&gt;Update our application to specify it is compatible with the new version of A&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, we need to make a new release of EVERY library that uses our base library and that is also used by our application. This can be very painful, and is a big waste of time if these intermediate libraries where not actually affected by the breaking change to begin with. This means that it is costly, and generally a bad idea, to have libraries depend on another library that is not very stable.&lt;/p&gt;

&lt;p&gt;Stability can be achieved in several ways. If the package is very abstract, and we assume good design, it will be stable. Think of a package providing a logging interface, such as psr/log. It can also be approached by a combination of following the package principles and taking care to avoid breaking changes.&lt;/p&gt;

&lt;p&gt;Conclusion: Keep the package principles in mind, and avoid depending on unstable libraries in your own libraries where possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  See also
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.entropywins.wtf/blog" rel="noopener noreferrer"&gt;My blog on software development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.entropywins.wtf/blog/2014/07/12/component-design/" rel="noopener noreferrer"&gt;Component Design (blog post)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bit.ly/component-design" rel="noopener noreferrer"&gt;Component Design (slides)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Package_principles" rel="noopener noreferrer"&gt;Package Principles (Wikipedia)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cleancode</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Iterators and Generators in PHP</title>
      <dc:creator>Jeroen De Dauw</dc:creator>
      <pubDate>Wed, 18 Oct 2017 07:27:09 +0000</pubDate>
      <link>https://forem.com/jeroendedauw/iterators-and-generators-in-php-e3p</link>
      <guid>https://forem.com/jeroendedauw/iterators-and-generators-in-php-e3p</guid>
      <description>&lt;p&gt;In this post I demonstrate an effective way to create iterators and generators in PHP and provide an example of a scenario in which using them makes sense. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://php.net/manual/en/language.generators.syntax.php" rel="noopener noreferrer"&gt;Generators&lt;/a&gt; have been around since PHP 5.5, and &lt;a href="https://secure.php.net/manual/en/class.iterator.php" rel="noopener noreferrer"&gt;iterators&lt;/a&gt; have been around since the Planck epoch. Even so, a lot of PHP developers do not know how to use them well and cannot recognize situations in which they are helpful. In this blog post I share insights I have gained over the years, that when sharing, always got an interested response from colleague developers. The post goes beyond the basics, provides a real world example, and includes a few tips and tricks. To not leave out those unfamiliar with Iterators the post starts with the "What are Iterators" section, which you can safely skip if you can already answer that question.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Iterators
&lt;/h3&gt;

&lt;p&gt;PHP has an &lt;code&gt;Iterator&lt;/code&gt; interface that you can implement to represent a collection. You can loop over an instance of an &lt;code&gt;Iterator&lt;/code&gt; just like you can loop over an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Iterator&lt;/span&gt; &lt;span class="nv"&gt;$things&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$things&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$thing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why would you bother implementing an &lt;code&gt;Iterator&lt;/code&gt; subclass rather than just using an array? Let's look at an example.&lt;/p&gt;

&lt;p&gt;Imagine you have a directory with a bunch of text files. One of the files contains an ASCII NyanCat (&lt;code&gt;~=[,,_,,]:3&lt;/code&gt;). It is the task of our code to find which file the NyanCat is hiding in.&lt;/p&gt;

&lt;p&gt;We can get all the files by doing a &lt;code&gt;glob( $path . '*.txt' )&lt;/code&gt; and we can get the contents for a file with a &lt;code&gt;file_get_contents&lt;/code&gt;. We could just have a foreach going over the glob result that does the &lt;code&gt;file_get_contents&lt;/code&gt;. Luckily we realize this would violate separation of concerns and make the "does this file contain NyanCat" logic hard to test since it will be bound to the filesystem access code. Hence we create a function that gets the contents of the files, and ones with our logic in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getContentsOfTextFiles&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// glob and file_get_contents&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;findTextWithNyanCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$texts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$texts&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;findNyanCat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;findTextWithNyanCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getContentsOfTextFiles&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this approach is &lt;strong&gt;decoupled&lt;/strong&gt;, a big drawback is that now we need to fetch the contents of all files and keep all of that in &lt;strong&gt;memory&lt;/strong&gt; before we even start executing any of our logic. If NyanCat is hiding in the first file, we'll have fetched the contents of all others for nothing. We can avoid this by using an &lt;code&gt;Iterator&lt;/code&gt;, as they can fetch their values on demand: they are &lt;strong&gt;lazy&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TextFileIterator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Iterator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// return file_get_contents&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;findTextWithNyanCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Iterator&lt;/span&gt; &lt;span class="nv"&gt;$texts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$texts&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;findNyanCat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;findTextWithNyanCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextFileIterator&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;TextFileIterator&lt;/code&gt; gives us a nice place to put all the filesystem code, while to the outside just looking like a collection of texts. The function housing our logic, &lt;code&gt;findTextWithNyanCat&lt;/code&gt;, does not know that the text comes from the filesystem. This means that if you decide to get texts from the database, you could just create a new DatabaseTextBlobIterator and pass it to the logic function without making any changes to the latter. Similarly, when testing the logic function, you can give it an &lt;code&gt;ArrayIterator&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testFindTextWithNyanCat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="nf"&gt;findTextWithNyanCat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayIterator&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'test text'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~=[,,_,,]:3'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrote more about basic &lt;code&gt;Iterator&lt;/code&gt; functionality in &lt;a href="https://www.entropywins.wtf/blog/2015/08/19/lazy-iterators-in-php-and-python/" rel="noopener noreferrer"&gt;Lazy iterators in PHP and Python&lt;/a&gt; and &lt;a href="https://www.entropywins.wtf/blog/2014/07/14/some-fun-with-iterators/" rel="noopener noreferrer"&gt;Some fun with iterators&lt;/a&gt;. I also blogged about a &lt;a href="https://www.entropywins.wtf/blog/2015/11/08/wikidata-wikibase-json-dump-reader/" rel="noopener noreferrer"&gt;library that provides some (Wikidata specific) iterators&lt;/a&gt; and a &lt;a href="https://www.entropywins.wtf/blog/2016/01/25/replicator-a-cli-tool-for-wikidata/" rel="noopener noreferrer"&gt;CLI tool build around an Iterator&lt;/a&gt;. For more on how generators work, see the off-site post &lt;a href="https://www.sitepoint.com/generators-in-php/" rel="noopener noreferrer"&gt;Generators in PHP&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  PHP's collection type hierarchy
&lt;/h3&gt;

&lt;p&gt;Let's start by looking at PHP's type hierarchy for collections as of PHP 7.1. These are the core types that I think are most important:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibt1kgxp7n5z4vmk9l6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibt1kgxp7n5z4vmk9l6d.png" alt="PHP iterable types" width="229" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the very top we have &lt;code&gt;iterable&lt;/code&gt;, the supertype of both &lt;code&gt;array&lt;/code&gt; and &lt;a href="https://secure.php.net/manual/en/class.traversable.php" rel="noopener noreferrer"&gt;&lt;code&gt;Traversable&lt;/code&gt;&lt;/a&gt;. If you are not familiar with this type or are using a version of PHP older than 7.1, don't worry, we don't need it for the rest of this blog post.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Iterator&lt;/code&gt; is the subtype of &lt;code&gt;Traversable&lt;/code&gt;, and the same goes for &lt;a href="https://secure.php.net/manual/en/class.iteratoraggregate.php" rel="noopener noreferrer"&gt;&lt;code&gt;IteratorAggregate&lt;/code&gt;&lt;/a&gt;. The standard library &lt;code&gt;iterator_&lt;/code&gt; functions such as &lt;code&gt;iterator_to_array&lt;/code&gt; all take a &lt;code&gt;Traversable&lt;/code&gt;. This is important since it means you can give them an &lt;code&gt;IteratorAggregate&lt;/code&gt;, even though it is not an &lt;code&gt;Iterator&lt;/code&gt;. Later on in this post we'll get back to what exactly an &lt;code&gt;IteratorAggregate&lt;/code&gt; is and why it is useful. &lt;/p&gt;

&lt;p&gt;Finally we have &lt;code&gt;Generator&lt;/code&gt;, which is a subtype of &lt;code&gt;Iterator&lt;/code&gt;. That means all functions that accept an &lt;code&gt;Iterator&lt;/code&gt; can be given a &lt;code&gt;Generator&lt;/code&gt;, and, by extension, that you can use generators in combination with the &lt;a href="https://secure.php.net/manual/en/spl.iterators.php" rel="noopener noreferrer"&gt;Iterator classes in the Standard PHP Library&lt;/a&gt; such as &lt;code&gt;LimitIterator&lt;/code&gt; and &lt;code&gt;CachingIterator&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  IteratorAggregate + Generator = &amp;lt;3
&lt;/h3&gt;

&lt;p&gt;Generators are a nice and easy way to create iterators. Often you'll only loop over them once, and not have any problem. However beware that generators create iterators that are not rewindable, which means that if you loop over them more than once, you'll get an exception.&lt;/p&gt;

&lt;p&gt;Imagine the scenario where you pass in a generator to a service that accepts an instance of &lt;code&gt;Traversable&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$aGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... yield ... */&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nv"&gt;$aService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$aGenerator&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;pre&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pre&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"lang:php decode:true"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Traversable&lt;/span&gt; &lt;span class="nv"&gt;$things&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$things&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$thing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The service class in which &lt;code&gt;doStuff&lt;/code&gt; resides does not know it is getting a &lt;code&gt;Generator&lt;/code&gt;, it just knows it is getting a &lt;code&gt;Traversable&lt;/code&gt;. When working on this class, it is entirely reasonable to iterate though &lt;code&gt;$things&lt;/code&gt; a second time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Traversable&lt;/span&gt; &lt;span class="nv"&gt;$things&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$things&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$thing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$things&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$thing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Boom if Generator!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This blows up if the provided &lt;code&gt;$things&lt;/code&gt; is a &lt;code&gt;Generator&lt;/code&gt;, because generators are non-rewindable. Note that it does not matter how you iterate through the value. Calling &lt;code&gt;iterator_to_array&lt;/code&gt; with &lt;code&gt;$things&lt;/code&gt; has the exact same result as using it in a foreach loop. Most, if not all, generators I have written, do not use resources or state that inherently prevents them from being rewindable. So the double-iteration issue can be unexpected and seemingly silly.&lt;/p&gt;

&lt;p&gt;There is a simple and easy way to get around it though. This is where &lt;code&gt;IteratorAggregate&lt;/code&gt; comes in. Classes implementing &lt;code&gt;IteratorAggregate&lt;/code&gt; must implement the &lt;code&gt;getIterator()&lt;/code&gt; method, which returns a &lt;code&gt;Traversable&lt;/code&gt;. Creating one of these is extremely trivial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AwesomeWords&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;\IteratorAggregate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getIterator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s1"&gt;'So'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s1"&gt;'Much'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s1"&gt;'Such'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you call &lt;code&gt;getIterator&lt;/code&gt;, you'll get a &lt;code&gt;Generator&lt;/code&gt; instance, just like you'd expect. However, normally you never call this method. Instead you use the &lt;code&gt;IteratorAggregate&lt;/code&gt; just as if it was an &lt;code&gt;Iterator&lt;/code&gt;, by passing it to code that expects a &lt;code&gt;Traversable&lt;/code&gt;. (This is also why usually you want to accept &lt;code&gt;Traversable&lt;/code&gt; and not just &lt;code&gt;Iterator&lt;/code&gt;.) We can now call our service that loops over the &lt;code&gt;$things&lt;/code&gt; twice without any problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$aService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AwesomeWords&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// no boom!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using &lt;code&gt;IteratorAggregate&lt;/code&gt; we did not just solve the non-rewindable problem, we also found a good way to share our code. Sometimes it makes sense to use the code of a &lt;code&gt;Generator&lt;/code&gt; in multiple classes, and sometimes it makes sense to have dedicated tests for the &lt;code&gt;Generator&lt;/code&gt;. In both cases having a dedicated class and file to put it in is very helpful, and a lot nicer than exposing the generator via some public static function.&lt;/p&gt;

&lt;p&gt;For cases where it does not make sense to share a &lt;code&gt;Generator&lt;/code&gt; and you want to keep it entirely private, you might need to deal with the non-rewindable problem. For those cases you can use my &lt;a href="https://github.com/JeroenDeDauw/RewindableGenerator" rel="noopener noreferrer"&gt;Rewindable Generator&lt;/a&gt; library, which allows making your generators rewindable by wrapping their creation function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$aGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... yield ... */&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nv"&gt;$aService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RewindableGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$aGenerator&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A real-world example
&lt;/h3&gt;

&lt;p&gt;A few months ago I refactored some code part of the &lt;a href="https://www.entropywins.wtf/blog/2016/11/24/implementing-the-clean-architecture/" rel="noopener noreferrer"&gt;Wikimedia Deutschland fundraising codebase&lt;/a&gt;. This code gets the filesystem paths of email templates by looking in a set of specified directories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getMailTemplatesOnDisk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$mailTemplatePaths&lt;/span&gt; &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$mailTemplatesOnDisk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$mailTemplatePaths&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$mailFilesInFolder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/Mail_*'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;array_walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$mailFilesInFolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// this would cause problems w/ mail templates in sub-folders&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$mailTemplatesOnDisk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$mailTemplatesOnDisk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$mailFilesInFolder&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$mailTemplatesOnDisk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code made the class bound to the filesystem, which made it hard to test. In fact, this code was not tested. Furthermore, this code irked me, since I like code to be on the functional side. The &lt;code&gt;array_walk&lt;/code&gt; mutates its by-reference variable and the assignment at the end of the loop mutates the return variable.&lt;/p&gt;

&lt;p&gt;This was refactored using the awesome &lt;code&gt;IteratorAggregate&lt;/code&gt; + &lt;code&gt;Generator&lt;/code&gt; combo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MailTemplateFilenameTraversable&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;\IteratorAggregate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$mailTemplatePaths&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mailTemplatePaths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$mailTemplatePaths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getIterator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;mailTemplatePaths&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/Mail_*'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$fileName&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nb"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$fileName&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Much easier to read/understand code, no state mutation whatsoever, good separation of concerns, easier testing and reusability of this collection building code elsewhere.&lt;/p&gt;

&lt;p&gt;See also: &lt;a href="http://blog.kevingomez.fr/2016/01/20/use-cases-for-php-generators/" rel="noopener noreferrer"&gt;Use cases for PHP generators&lt;/a&gt; (off-site post).&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips and Tricks
&lt;/h3&gt;

&lt;p&gt;Generators can yield key value pairs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;"Iterators"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"are useful"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;"Generators"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"are awesome"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// [ "Iterators" =&amp;gt; "are useful", "Generators" =&amp;gt; "are awesome" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use &lt;a href="https://www.entropywins.wtf/blog/2017/10/09/yield-in-phpunit-data-providers/" rel="noopener noreferrer"&gt;yield in PHPUnit data providers&lt;/a&gt;. You can &lt;em&gt;yield from&lt;/em&gt; an &lt;code&gt;iterable&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayIterator&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// 1, 2, 3, 4, 5 &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Flattens iterable[] into Generator&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$collections&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for Leszek Manicki and Jan Dittrich for reviewing this blog post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://www.entropywins.wtf/blog/" rel="noopener noreferrer"&gt;blog&lt;/a&gt; as &lt;a href="https://www.entropywins.wtf/blog/2017/10/16/introduction-to-iterators-and-generators-in-php/" rel="noopener noreferrer"&gt;Introduction to Iterators and Generators in PHP&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>iterators</category>
      <category>generators</category>
    </item>
    <item>
      <title>Yield in PHPUnit data providers</title>
      <dc:creator>Jeroen De Dauw</dc:creator>
      <pubDate>Wed, 11 Oct 2017 03:09:10 +0000</pubDate>
      <link>https://forem.com/jeroendedauw/yield-in-phpunit-data-providers-9l</link>
      <guid>https://forem.com/jeroendedauw/yield-in-phpunit-data-providers-9l</guid>
      <description>&lt;p&gt;Initially I started creating a general post about &lt;a href="https://secure.php.net/manual/en/language.generators.syntax.php" rel="noopener noreferrer"&gt;PHP Generators&lt;/a&gt;, a feature introduced in PHP 5.5. However since I keep failing to come up with good examples for some cool ways to use Generators, I decided to do this mini post focusing on one such cool usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  PHPUnit data providers
&lt;/h2&gt;

&lt;p&gt;A commonly used &lt;a href="http://phpunit.de/" rel="noopener noreferrer"&gt;PHPUnit&lt;/a&gt; feature is &lt;a href="https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers" rel="noopener noreferrer"&gt;data providers&lt;/a&gt;. In a data provider you specify a list of argument lists, and the test methods that use the data provider get called once for each argument list.&lt;/p&gt;

&lt;p&gt;Often data providers are created with an array variable in which the argument lists get stuffed. Example (including poor naming):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * @dataProvider provideUserInfo
 */&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testSomeStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$userAge&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;provideUserInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$return&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="nv"&gt;$return&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'Such Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$return&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'Very Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$return&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Named parameter set'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'So Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1337&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The not so nice thing here is that you have a variable (explicit state) and you modify it (mutable state). A more functional approach is to just return an array that holds the argument lists directly. However if your argument list creation is more complex than in this example, requiring state, this might not work. And when such state is required, you end up with more complexity and a higher chance that the &lt;code&gt;$return&lt;/code&gt; variable will bite you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using yield
&lt;/h2&gt;

&lt;p&gt;What you might not have realized is that data providers do not need to return an array. They need to return an &lt;code&gt;iterable&lt;/code&gt;, so they can also return an &lt;code&gt;Iterator&lt;/code&gt;, and by extension, a &lt;code&gt;Generator&lt;/code&gt;. This means you can write the above data provider as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;provideUserInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'Such Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'Very Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s1"&gt;'Named parameter set'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'So Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1337&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No explicit state to be seen!&lt;/p&gt;

&lt;p&gt;Stay tuned for more generator goodness if I can overcome my own &lt;em&gt;laziness&lt;/em&gt; (hint hint :))&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://www.entropywins.wtf/blog/" rel="noopener noreferrer"&gt;blog&lt;/a&gt; as &lt;a href="https://www.entropywins.wtf/blog/2017/10/09/yield-in-phpunit-data-providers/" rel="noopener noreferrer"&gt;Yield in PHPUnit data providers&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cleancode</category>
      <category>php</category>
      <category>generators</category>
    </item>
    <item>
      <title>The Fallacy of DRY</title>
      <dc:creator>Jeroen De Dauw</dc:creator>
      <pubDate>Sat, 16 Sep 2017 17:36:14 +0000</pubDate>
      <link>https://forem.com/jeroendedauw/the-fallacy-of-dry</link>
      <guid>https://forem.com/jeroendedauw/the-fallacy-of-dry</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://www.entropywins.wtf/blog/" rel="noopener noreferrer"&gt;blog&lt;/a&gt; as &lt;a href="https://www.entropywins.wtf/blog/2017/09/06/the-fallacy-of-dry/" rel="noopener noreferrer"&gt;The Fallacy of DRY&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;DRY, standing for &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;Don’t Repeat Yourself&lt;/a&gt;, is a well-known design principle in the software development world.&lt;/p&gt;

&lt;p&gt;It is not uncommon for removal of duplication to take center stage via mantras such as “Repetition is the root of all evil”. Yet while duplication is often bad, the well intended pursuit of DRY often leads people astray. To see why, let’s take a step back and look at what we want to achieve by removing duplication.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal of Software
&lt;/h2&gt;

&lt;p&gt;First and foremost, software exists to fulfill a purpose. Your client, which can be your employer, is paying money because they want the software to provide value. As a developer it is your job to provide this value as effectively as possible. This includes tasks beyond writing code to do whatever your client specifies, and might best be done by not writing any code. The creation of code is expensive. Maintenance of code and extension of legacy code is even more so.&lt;/p&gt;

&lt;p&gt;Since creation and maintenance of software is expensive, the quality of a developers work (when just looking at the code) can be measured in how quickly functionality is delivered in a satisfactory manner, and how easy to maintain and extend the system is afterwards. Many design discussions arise about trade-offs between those two measures. The DRY principle mainly situates itself in the latter category: reducing maintenance costs. Unfortunately applying DRY blindly often leads to increased maintenance costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Good Side of DRY
&lt;/h2&gt;

&lt;p&gt;So how does DRY help us reduce maintenance costs? If code is duplicated, and it needs to be changed, you will need to find all places where it is duplicated and apply the change. This is (obviously) more difficult than modifying one place, and more error prone. You can forget about one place where the change needs to be applied, you can accidentally apply it differently in one location, or you can modify code that happens to the same at present but should nevertheless not be changed due to conceptual differences (more on this later). This is also known as &lt;a href="https://en.wikipedia.org/wiki/Shotgun_surgery" rel="noopener noreferrer"&gt;Shotgun Surgery&lt;/a&gt;. Duplicated code tends to also obscure the structure and intent of your code, making it harder to understand and modify. And finally, it conveys a sense of carelessness and lack of responsibility, which begets more carelessness.&lt;/p&gt;

&lt;p&gt;Everyone that has been in the industry for a little while has come across horrid procedural code, or perhaps pretend-OO code, where copy-paste was apparently the favorite hammer of its creators. Such programmers indeed should heed DRY, cause what they are producing suffers from the issues we just went over. So where is The Fallacy of DRY?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fallacy of DRY
&lt;/h2&gt;

&lt;p&gt;Since removal of duplication is a means towards more maintainable code, we should only remove duplication if that removal makes the code more maintainable.&lt;/p&gt;

&lt;p&gt;If you are reading this, presumably you are not a copy-and-paste programmer. Almost no one I ever worked with is. Once you know how to create well designed OO applications (ie by knowing the &lt;a href="https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)" rel="noopener noreferrer"&gt;SOLID principles&lt;/a&gt;), are writing tests, etc, the code you create will be very different from the work of a copy-paste-programmer. Even when adhering to the SOLID principles (to the extend that it makes sense) there might still be duplication that should be removed.The catch here is that this duplication will be mixed together with duplication that should stay, since removing it makes the code less maintainable. Hence trying to remove all duplication is likely to be counter productive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Costs of Unification
&lt;/h2&gt;

&lt;p&gt;How can removing duplication make code less maintainable? If the costs of unification outweigh the costs of duplication, then we should stick with duplication. We’ve already gone over some of the costs of duplication, such as the need for Shotgun Surgery. So let’s now have a look at the costs of unification.&lt;/p&gt;

&lt;p&gt;The first cost is added &lt;strong&gt;complexity&lt;/strong&gt;. If you have two classes with a little bit of common code, you can extract this common code into a service, or if you are a masochist extract it into a base class. In both cases you got rid of the duplication by introducing a new class. While doing this you might reduce the total complexity by not having the duplication, and such extracting might make sense in the first place for instance to avoid a Single Responsibility Principle violation. Still, if the only reason for the extraction is reducing duplication, ask yourself if you are reducing the overall complexity or adding to it.&lt;/p&gt;

&lt;p&gt;Another cost is &lt;strong&gt;coupling&lt;/strong&gt;. If you have two classes with some common code, they can be fully independent. If you extract the common code into a service, both classes will now depend upon this service. This means that if you make a change to the service, you will need to pay attention to both classes using the service, and make sure they do not break. This is especially a problem if the service ends up being extended to do more things, though that is more of a SOLID issue. I’ll skip going of the results of code reuse via inheritance to avoid suicidal (or homicidal) thoughts in myself and my readers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DRY = Coupling&lt;br&gt;
– A slide at DDDEU 2017&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The coupling increases the need for &lt;strong&gt;communication&lt;/strong&gt;. This is especially true in the large, when talking about unifying code between components or application, and when different teams end up depending on the same shared code. In such a situation it becomes very important that it is clear to everyone what exactly is expected from a piece of code, and making changes is often slow and costly due to the communication needed to make sure they work for everyone.&lt;/p&gt;

&lt;p&gt;Another result of unification is that code can no longer &lt;strong&gt;evolve separately&lt;/strong&gt;. If we have our two classes with some common code, and in the first a small behavior change is needed in this code, this change is easy to make. If you are dealing with a common service, you might do something such as adding a flag. That might even be the best thing to do, though it is likely to be harmful design wise. Either way, you start down the path of &lt;strong&gt;corrupting your service&lt;/strong&gt;, which now turned into a frog in a pot of water that is being heated. If you unified your code, this is another point at which to ask yourself if that is still the best trade-off, or if some duplication might be easier to maintain.&lt;/p&gt;

&lt;p&gt;You might be able to represent two &lt;strong&gt;different concepts&lt;/strong&gt; with the same bit of code. This is problematic not only because different concepts need to be able to evolve individually, it’s also &lt;strong&gt;misleading&lt;/strong&gt; to have only a single representation in the code, which effectively hides that you are dealing with two different concepts. This is another point that gains importance the bigger the scope of reuse. Domain Driven Design has a strategic pattern called &lt;a href="http://martinfowler.com/bliki/BoundedContext.html" rel="noopener noreferrer"&gt;Bounded Contexts&lt;/a&gt;, which is about the separation of code that represents different (sub)domains. Generally speaking it is good to avoid sharing code between Bounded Contexts. You can find a concrete example of using the same code for two different concepts in my blog post on &lt;a href="https://www.entropywins.wtf/blog/2016/11/24/implementing-the-clean-architecture/" rel="noopener noreferrer"&gt;Implementing the Clean Architecture&lt;/a&gt;, in the section “Lesson learned: bounded contexts”.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;DRY is for one Bounded Context&lt;br&gt;
– Eric Evans in &lt;a href="https://www.youtube.com/watch?v=lY54TmmEllY" rel="noopener noreferrer"&gt;Good Design is Imperfect Design&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Duplication itself does not matter. We care about code being easy (cheap) to modify without introducing regressions. Therefore we want &lt;a href="https://www.entropywins.wtf/blog/2017/01/02/simple-is-not-easy/" rel="noopener noreferrer"&gt;simple code that is easy to understand&lt;/a&gt;. Pursuing removal of duplication as an end-goal rather than looking at the costs and benefits tends to result in a more complex codebase, with higher coupling, higher communication needs, inferior design and misleading code.&lt;/p&gt;

</description>
      <category>cleancode</category>
      <category>dry</category>
      <category>antipatterns</category>
      <category>designpatterns</category>
    </item>
  </channel>
</rss>
