<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/design/</id>
  <link href="https://www.endpointdev.com/blog/tags/design/"/>
  <link href="https://www.endpointdev.com/blog/tags/design/" rel="self"/>
  <updated>2026-04-06T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>High Level System Analysis and Design with Domain-Driven Design</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/"/>
      <id>https://www.endpointdev.com/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/</id>
      <published>2026-04-06T00:00:00+00:00</published>
      <author>
        <name>Kevin Campusano</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/pines-waterfall.webp&#34; alt=&#34;A wide waterfall cascades through a rocky, forested canyon surrounded by pine-covered hills under a cloudy sky.&#34;&gt;&lt;br&gt;
Photo by Zed Jensen, 2022.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Domain-Driven Design&lt;/strong&gt; is an approach to software development that focuses on, &lt;a href=&#34;https://www.oreilly.com/library/view/domain-driven-design-tackling/0321125215/&#34;&gt;as Eric Evans puts it&lt;/a&gt;, &amp;ldquo;tackling the complexity in the heart of software&amp;rdquo;. And what is in the heart of software? The business domain in which it operates. Or more specifically: a &lt;strong&gt;model&lt;/strong&gt; of it, made of code. That is, the code that implements the business logic that comes into play when solving problems within the realm of a particular business activity.&lt;/p&gt;
&lt;p&gt;DDD is not just about writing code though. It&amp;rsquo;s a whole methodology that touches on business needs, requirements gathering, organizational dynamics, high level architectural design, and lower level patterns for implementing software intensive systems.&lt;/p&gt;
&lt;p&gt;As a result, DDD offers a treasure trove of concepts, patterns and tools that can be applied to any software project, regardless of the size and complexity.&lt;/p&gt;
&lt;p&gt;In this series of blog posts we&amp;rsquo;re going to explore many aspects of DDD. We will be following the structure laid out by &lt;a href=&#34;https://vladikk.com/&#34;&gt;Vlad Khononov&lt;/a&gt;&amp;rsquo;s excellent book on the topic &amp;ldquo;&lt;a href=&#34;https://www.oreilly.com/library/view/learning-domain-driven-design/9781098100124/&#34;&gt;Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy&lt;/a&gt;&amp;rdquo;. So you can think of this series as a summary of that book. An abridged version that can serve as a review for anybody who has read it; but also as an entry point for people who are new to DDD.&lt;/p&gt;
&lt;h3 id=&#34;table-of-contents&#34;&gt;Table of contents&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#high-level-system-analysis-and-design-with-domain-driven-design&#34;&gt;High level system analysis and design with Domain-Driven Design&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#table-of-contents&#34;&gt;Table of contents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#section-1-analyzing-business-domains&#34;&gt;Section 1. Analyzing business domains&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#domains-and-subdomains&#34;&gt;Domains and subdomains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#types-of-subdomains&#34;&gt;Types of subdomains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#using-subdomains-to-make-strategic-decisions&#34;&gt;Using subdomains to make strategic decisions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#section-2-discovering-domain-knowledge&#34;&gt;Section 2. Discovering domain knowledge&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#the-ubiquitous-language&#34;&gt;The ubiquitous language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-ubiquitous-language-as-a-model-of-the-domain&#34;&gt;The ubiquitous language as a model of the domain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#tools-for-capturing-the-ubiquitous-language&#34;&gt;Tools for capturing the ubiquitous language&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#section-3-managing-domain-complexity&#34;&gt;Section 3. Managing domain complexity&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#reasons-for-creating-bounded-contexts&#34;&gt;Reasons for creating bounded contexts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#bounded-contexts-vs-subdomains&#34;&gt;Bounded contexts vs subdomains&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#section-4-integrating-bounded-contexts&#34;&gt;Section 4. Integrating bounded contexts&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#cooperation-patterns&#34;&gt;Cooperation patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#customer-supplier-patterns&#34;&gt;Customer-supplier patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#separate-ways&#34;&gt;Separate ways&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-context-map&#34;&gt;The context map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-ddd-high-level-design-concept-map&#34;&gt;The DDD high level design concept map&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;section-1-analyzing-business-domains&#34;&gt;Section 1. Analyzing business domains&lt;/h3&gt;
&lt;p&gt;It is a well understood notion that before writing code, we need to understand the problem we&amp;rsquo;re trying to solve. DDD is consistent with this notion and argues that developers need to, first and foremost, gain an understanding of the business that the software is being built for. To this end, DDD relies on three concepts: domains, subdomains and domain experts.&lt;/p&gt;
&lt;h4 id=&#34;domains-and-subdomains&#34;&gt;Domains and subdomains&lt;/h4&gt;
&lt;p&gt;In simple terms, the &lt;strong&gt;domain&lt;/strong&gt; of a business is what it does, its area of activity. For example, Starbucks is in the business of making coffee, Ford is in the business of making automobiles, AMC is in the business of movie theaters.&lt;/p&gt;
&lt;p&gt;Of course, analyzing a business as a single integrated whole can be unmanageable. That&amp;rsquo;s where subdomains come in. &lt;strong&gt;Subdomains&lt;/strong&gt; are the different divisions within a domain. Starbuck&amp;rsquo;s domain for example, is making coffee. But there are many smaller parts that make up that business and allow it to be successful. There&amp;rsquo;s of course, the subdomain of coffee preparation. But there&amp;rsquo;s also real estate management to find and secure good locations, there&amp;rsquo;s inventory management and logistics, there&amp;rsquo;s marketing, there&amp;rsquo;s human resources, etc. All these are the subdomains that make up the overall business of Starbucks.&lt;/p&gt;
&lt;p&gt;Depending on the business and on the project, these will vary greatly in granularity. And you can also decompose subdomains further and discover new fine-grained subdomains nested within more coarse-grained ones. The sizes and nesting levels can be very different from business to business, so it can be difficult to clearly delineate where a subdomain ends and another one starts, which activities belong to one or the other. One good rule of thumb to keep in mind is that generally, subdomains encapsulate a set of coherent, closely related use cases. That is, use cases that involve the same set of closely related actors, business entities and/or data.&lt;/p&gt;
&lt;p&gt;And finally, we have &lt;strong&gt;domain experts&lt;/strong&gt;. As the name suggests, these are the people within the organization who have intimate knowledge of the business, or certain areas of it. They are the subject matter experts. Usually they are the ones who identify the problems and come up with requirements. Developers need to rely on domain experts to gain the necessary understanding to be able to produce useful software solutions.&lt;/p&gt;
&lt;p&gt;So, when approaching software projects, DDD suggests that developers work closely with domain experts in order to learn from them about the business domain and subdomains. After all, it is their mental models and understanding that will be modeled and implemented in code.&lt;/p&gt;
&lt;h4 id=&#34;types-of-subdomains&#34;&gt;Types of subdomains&lt;/h4&gt;
&lt;p&gt;With the help of domain experts, developers can identify subdomains, understand their business value and how they fit within the overall business strategy. This is very important because it helps making some initial architecturally significant decisions. Namely, the general approach to solving the problems in the subdomains, how much to invest, how to organize development teams, etc. The main objective in this analysis stage is to identify the subdomains and whether they fall into one of three types: core, generic, and supporting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Core subdomains&lt;/strong&gt; are the activities of the business with highest value. The ones that confer differentiation in the market and a competitive advantage. They are the business&amp;rsquo; raison d&amp;rsquo;être. For example, for Google, their search engine is a core subdomain. For Ford, their automotive engineering area would be a core subdomain. Core subdomains are generally the most complex parts of the business. They are constantly evolving and improving, and the company is compelled to invest heavily in them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generic subdomains&lt;/strong&gt; are also very complex. However, they are not business differentiators. Instead, these are the areas of the business that all organizations handle in the same way. Think accounting, a ticketing system, an online storefront. There&amp;rsquo;s no pressure to innovate in these areas, so the solutions are very stable and evolution is slow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Supporting subdomains&lt;/strong&gt; on the other hand, do not provide any competitive advantage, nor are they very complex. They are however, necessary because they support the core business activities, and are fairly unique. The solutions to problems in these areas usually take the form of &lt;a href=&#34;https://en.wikipedia.org/wiki/Create,_read,_update_and_delete&#34;&gt;CRUD&lt;/a&gt; or &lt;a href=&#34;https://en.wikipedia.org/wiki/Extract,_transform,_load&#34;&gt;ETL&lt;/a&gt; oriented activities. Imagine for example populating a data warehouse, translating transactional business data into a format appropriate for analytics and business intelligence in a manufacturing corporation. Or maybe the digitization and storage of a registry of court documents for a law firm. These are behind the scenes activities that support the organizations&amp;rsquo; main businesses, but their business logic complexity is not high, and they don&amp;rsquo;t really represent big selling points for the company.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s worth noting as well, that there may be subdomains where software solutions are not appropriate, even if they are highly complex core subdomains. They are still part of the business so it&amp;rsquo;s worth identifying and considering for high level architectural design decisions. If anything, to know what parts of the business the planned software system should and should not focus on. You could have a restaurant, for example, who prides itself in having the best desserts in the city. For their business, the recipe development activities constitute a core subdomain. This is dependent on the art and craftsmanship of the chefs. Not an area in which software solutions could help a whole lot.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also worth noting that, just as organizations&amp;rsquo; business strategies are dynamic, so too can be their subdomain distribution. Today&amp;rsquo;s generic subdomain can be tomorrow&amp;rsquo;s core subdomain, and so on. For example, imagine a big retail store chain that, up until now, managed its inventory in an industry standard way. But it has grown so much that the standard way of doing things has become a bottleneck for them. So they design a new procedure for highly efficient inventory management, and that gives them an edge against competitors. Inventory management started as a generic subdomain for them, but due to an ever evolving business strategy, it became a core subdomain.&lt;/p&gt;
&lt;p&gt;The knowledge of subdomain types can also help the analysis when dividing the business and discovering subdomains. If you find yourself recursively finding more and more fine-grained subdomains from already identified ones, a good time to stop recursing is when you find that a generic or supporting subdomain, when broken down, reveals only new finer-grained generic or supporting subdomains. The reasoning for this is simple: this analysis activity is most valuable when trying to identify core subdomains. When there are no more core subdomains to be found within a particular area of the business, then it&amp;rsquo;s probably not worth it to keep digging deeper.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/decomposing-a-generic-subdomain.png&#34; alt=&#34;Decomposing a generic subdomain&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Here we have an example of a hypothetical help desk system subdomain, part of a customer service subdomain, being decomposed and revealing that it only contains generic subdomains.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In summary, these are the main characteristics of the three types of subdomains:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Core subdomains&lt;/strong&gt; have high complexity, provide competitive advantage, and change and evolve frequently.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generic subdomains&lt;/strong&gt; have high complexity, do not provide competitive advantage and change overtime, although at a slower pace than core subdomains.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support subdomains&lt;/strong&gt; have low complexity, do not provide competitive advantage and are the slowest to change.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/subdomain-types-complexity-vs-differentiation.png&#34; alt=&#34;Subdomain types complexity vs differentiation&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is where each type of subdomain fall when considering their business logic complexity and business differentiation.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;using-subdomains-to-make-strategic-decisions&#34;&gt;Using subdomains to make strategic decisions&lt;/h4&gt;
&lt;p&gt;Like I&amp;rsquo;ve already alluded to, armed with this knowledge, DDD practitioners are ready to start making some higher level architectural decisions. Depending on the type of subdomain that a problem belongs to, DDD has specific prescriptions on how to handle the implementation of software solutions for them.&lt;/p&gt;
&lt;p&gt;When working on &lt;strong&gt;core subdomains&lt;/strong&gt;, that&amp;rsquo;s where we want to make the biggest investments. We deploy the most advanced engineering tools, patterns and practices. This is to make sure that the software is efficient and high quality, and also easy to maintain and evolve. This is necessary because core subdomains have to evolve rapidly by nature, if the business is to maintain competitive advantage. Software solutions that operate within the context of core subdomains have to be implemented by high skill and high trust teams. Either in-house, or via trusted development partners, working hand in hand with domain experts.&lt;/p&gt;
&lt;p&gt;Problems in &lt;strong&gt;generic subdomains&lt;/strong&gt;, by nature of their business logic being very complex but also very common, are likely to have already been solved. For these types of problems, DDD recommends against implementing custom software, and instead buying and/or adopting tried and true, industry standard, off-the-shelf solutions. Their implementation and integration can be outsourced or handled by less specialized or skilled teams. The change management of these solutions is simple, as they get delivered generally via patches and updates.&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;support subdomains&lt;/strong&gt;, whose business logic is generally simple but uncommon, it is less likely that off-the-shelf solutions would be available. So software addressing problems in these subdomains will most likely have to be implemented as custom solutions. Due to their low complexity though, they can be easily outsourced, or handled by more junior team members. They can also be handled with &lt;a href=&#34;https://en.wikipedia.org/wiki/Rapid_application_development&#34;&gt;RAD&lt;/a&gt;, low-to-no-code technologies, since often times they are little more than ETL and pure CRUD applications.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a table to summarizes the differences between the types of subdomains:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Type of subdomain&lt;/th&gt;
          &lt;th&gt;Core&lt;/th&gt;
          &lt;th&gt;Generic&lt;/th&gt;
          &lt;th&gt;Supporting&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Competitive advantage&lt;/td&gt;
          &lt;td&gt;Yes&lt;/td&gt;
          &lt;td&gt;No&lt;/td&gt;
          &lt;td&gt;No&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Complexity&lt;/td&gt;
          &lt;td&gt;High&lt;/td&gt;
          &lt;td&gt;High&lt;/td&gt;
          &lt;td&gt;Low&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Rate of change&lt;/td&gt;
          &lt;td&gt;High&lt;/td&gt;
          &lt;td&gt;Medium&lt;/td&gt;
          &lt;td&gt;Low&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Implementation&lt;/td&gt;
          &lt;td&gt;Custom development&lt;/td&gt;
          &lt;td&gt;Buy/adopt off-the-shelf&lt;/td&gt;
          &lt;td&gt;Custom development&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Team composition&lt;/td&gt;
          &lt;td&gt;In-house/partners&lt;/td&gt;
          &lt;td&gt;Can outsource&lt;/td&gt;
          &lt;td&gt;Can outsource&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Skill level&lt;/td&gt;
          &lt;td&gt;High&lt;/td&gt;
          &lt;td&gt;High/regular&lt;/td&gt;
          &lt;td&gt;Low&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Investment&lt;/td&gt;
          &lt;td&gt;High&lt;/td&gt;
          &lt;td&gt;Medium&lt;/td&gt;
          &lt;td&gt;Low&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Problems&lt;/td&gt;
          &lt;td&gt;Interesting&lt;/td&gt;
          &lt;td&gt;Solved&lt;/td&gt;
          &lt;td&gt;Simple&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;section-2-discovering-domain-knowledge&#34;&gt;Section 2. Discovering domain knowledge&lt;/h3&gt;
&lt;p&gt;After identifying the business domain and categorizing the various subdomains that compose it, we have a bird&amp;rsquo;s-eye view of the business. This is good enough to get started and make high level architectural decisions of potential software solutions to problems within these domains. To actually build the software though, we need much more than that. In order to gain a thorough understanding of the business logic, and be able to eventually model and implement it in code, DDD proposes the &lt;strong&gt;ubiquitous language&lt;/strong&gt; as a tool.&lt;/p&gt;
&lt;h4 id=&#34;the-ubiquitous-language&#34;&gt;The ubiquitous language&lt;/h4&gt;
&lt;p&gt;The &lt;strong&gt;ubiquitous language&lt;/strong&gt; is DDD&amp;rsquo;s tool for knowledge sharing, effective communication and software modeling. In simple terms, the ubiquitous language is the language of the business. It&amp;rsquo;s the language that domain experts use on a day to day basis to talk and reason about the business.&lt;/p&gt;
&lt;p&gt;For a software project to be successful, it&amp;rsquo;s essential that engineers and stakeholders understand each other. They have to be aligned when it comes to the meanings of the core concepts of the business domain. That&amp;rsquo;s why it&amp;rsquo;s so important that everybody uses the ubiquitous language for all project related communications, requirements, documentation, face to face discussions, and even code itself. It all needs to share the same language.&lt;/p&gt;
&lt;p&gt;Engineers will need to interact with domain experts in order to learn about the business domain and its rules. They need to acquire the necessary knowledge that allows them to implement these rules in the software. During these interactions, they converse using the ubiquitous language. However, the knowledge transfer is not always strictly unidirectional. Yes, engineers have to learn from the domain experts. But also, through conversations and questioning, engineers can help domain experts deepen and flesh out their own understanding about their domains.&lt;/p&gt;
&lt;p&gt;A classic example of this is when domain experts focus too much on the &amp;ldquo;happy paths&amp;rdquo; of given business processes. Then, through discussions with developers, on account of the inherent precision that software demands, they are forced to consider more edge cases, better specify ambiguous terms and fill out gaps in their understanding.&lt;/p&gt;
&lt;p&gt;This deepening of knowledge feeds back into the ubiquitous language and improves it. Making it more insightful and more precise. This means that, throughout the life cycle of a project, the ubiquitous language should keep evolving, expanding and refining. This allows it to continuously improve as an effective model of the business domain, for the problem that it&amp;rsquo;s trying to solve. Indeed, just like code is a model of the business domain, so too is the ubiquitous language.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/traditional-knowledge-sharing-flow.png&#34; alt=&#34;Traditional knowledge sharing flow&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A classic pitfall in software projects is a manner of communication and knowledge sharing where developers are various steps removed from the domain experts. Consistent use of the ubiquitous language addresses this.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;the-ubiquitous-language-as-a-model-of-the-domain&#34;&gt;The ubiquitous language as a model of the domain&lt;/h4&gt;
&lt;p&gt;Through consistent use of the ubiquitous language, developers are able to obtain a deeper understanding of the domain, the problems we&amp;rsquo;re trying to solve, the reasoning behind the requirements and the mental model of the domain experts. This allows the construction of effective software solutions, with deep business insight, that go beyond simply translating requirements into code. If the implementation models the business domain effectively, there is potential for it to evolve with the business and better adapt as requirements change; and we reduce the risk of missing edge cases that may not be obvious to domain experts.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/knowledge-sharing-in-ddd.png&#34; alt=&#34;Knowledge sharing under DDD&#34;&gt;
&lt;em&gt;Under DDD, developers and domain experts develop the ubiquitous language, which then informs the implementation.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Effectively, when we build a ubiquitous language, we&amp;rsquo;re building a model of the domain. A model that reflects the relevant business entities, their behavior, and relationships. A model that will be eventually implemented into code, but also a model that needs to be understood by all stakeholders, regardless of their technical level. So it needs to be precise and rigorous, but also understandable. As such, in order to be useful, the ubiquitous language needs to respect certain restrictions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It must not include technical jargon like programming languages, constructs or frameworks; nor mention specific system structures like database tables, servers or programs. It is the language of the business and it needs to be understandable by non technical folks.&lt;/li&gt;
&lt;li&gt;It must avoid using the same term for different concepts. In conversation with humans, a lot of the meaning is extracted from the context. In software, not so much. Just like you can&amp;rsquo;t have two classes with the same name within the same namespace, the ubiquitous language cannot allow such ambiguities.&lt;/li&gt;
&lt;li&gt;It should also avoid using different words for the same concept. The classic example for this is words like users, accounts, customers, visitors. They all refer to closely related concepts which might actually have differences. The problem with these overlapping terms is that those differences are obscured by the notion of them &amp;ldquo;being the same&amp;rdquo; and being used interchangeably. For usage within the ubiquitous language, it&amp;rsquo;s best to be precise and clearly delineate terms and definitions. Eliminate what&amp;rsquo;s redundant, be strict with definitions.&lt;/li&gt;
&lt;li&gt;It should avoid including extraneous details. Just like code needs to include only what&amp;rsquo;s needed to solve the problem at hand and nothing else (in order to avoid accidental complexity); the ubiquitous language must not be polluted with details from outside of the area of business activity that it represents. That can create confusion and unnecessary cognitive load.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/model-translations.png&#34; alt=&#34;Classic model translations&#34;&gt;
&lt;em&gt;The ubiquitous language represents a unified model of the domain. This is in contrast to a more traditional process where domain knowledge gets &amp;ldquo;translated&amp;rdquo; multiple times before turning into code.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;tools-for-capturing-the-ubiquitous-language&#34;&gt;Tools for capturing the ubiquitous language&lt;/h4&gt;
&lt;p&gt;The &lt;a href=&#34;https://agilemanifesto.org/&#34;&gt;Agile Manifesto&lt;/a&gt; declares: &amp;ldquo;Individuals and interactions over processes and tools&amp;rdquo;. And of course, when it comes to the ubiquitous language, direct interaction and conversations between engineers, domain experts and other stakeholders reigns supreme. That&amp;rsquo;s when it can be most useful. It can also be useful, however, to capture the ubiquitous language in documentation and even in runnable form.&lt;/p&gt;
&lt;p&gt;A glossary of terms is a great asset for keeping a ubiquitous language. A wiki is a good place to put this. Definitions for key concepts in the business like entities, processes and rules can be captured here. The only caveat is that documentation is static by nature, while the ubiquitous language is continually evolving. So, great care needs to be taken to keep the wiki updated at all times to reflect the latest and most complete understanding of the domain. This should not be relegated to or gate-keeped by only certain people; it should be a team effort where everyone contributes.&lt;/p&gt;
&lt;p&gt;An automated acceptance tests suite, written using &lt;a href=&#34;https://en.wikipedia.org/wiki/Behavior-driven_development&#34;&gt;Behavior Driven Development&lt;/a&gt; frameworks, like &lt;a href=&#34;https://cucumber.io/&#34;&gt;Cucumber&lt;/a&gt;, is also a great way of capturing the ubiquitous language. The advantage of these tests is that they are written in plain human-readable language, not code. And while it may be far fetched to think that non technical domain experts would be capable of writing and maintaining such tests, they certainly can read and understand them, which is a great boon. These tests speak the language they understand: the language of the business.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/cucumber.png&#34; alt=&#34;Cucumber tests&#34;&gt;
&lt;em&gt;This is what Cucumber tests look like.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By nature of being executable and tied closely to the implementation code, there is less chance that they become out of date. This can happen more easily with static documentation written in a wiki. The disadvantage is that they require much more effort. But for the right kind of project, one where business logic is very complex or the scope is very wide, they can be very well worth the cost.&lt;/p&gt;
&lt;h3 id=&#34;section-3-managing-domain-complexity&#34;&gt;Section 3. Managing domain complexity&lt;/h3&gt;
&lt;p&gt;We can attempt to model an entire business domain with one big ubiquitous language, but sometimes that&amp;rsquo;s impossible. Especially so for businesses of a certain size, you will inevitably find inconsistencies and conflicts between the mental models of different domain experts. The simplest example of this scenario is when different experts from different areas of the organization have the same word to describe different concepts. Or when they look at the same business entity with different levels of detail.&lt;/p&gt;
&lt;p&gt;When the different mental models are valid, and these inconsistencies are legitimate and cannot be reconciled, the solution is to follow the divide and conquer principle and decompose the language into separate ones, each one working within its own bounded context.&lt;/p&gt;
&lt;p&gt;Simply put, a &lt;strong&gt;bounded context&lt;/strong&gt; is the context within which a ubiquitous language, and the model it represents, operate, have meaning and are useful. Sure enough, just like a domain can be divided into subdomains, a ubiquitous language can be decomposed into smaller languages, each with its own context, to model different parts of the business. While we can attempt to capture an entire business domain with a single model, this is not advisable in the case of complex systems. It&amp;rsquo;s better to split up the model into smaller, more precise ones, tailored to work on specific problem domains.&lt;/p&gt;
&lt;h4 id=&#34;reasons-for-creating-bounded-contexts&#34;&gt;Reasons for creating bounded contexts&lt;/h4&gt;
&lt;p&gt;Like mentioned before, different domain experts having conflicting mental models is a clear indication that a division in the model needs to happen. However, that only tells us half of the story. There are other indicators that point to when and where further division should happen:&lt;/p&gt;
&lt;p&gt;First of all, there is of course, size. Size by itself is not a deciding factor, but it is something to consider and balance. Fewer, bigger models can help keep the overall environment simpler, but if they become too big they can become unmanageable and prone to corruption. A higher number of smaller models keep cognitive load low, but you run the risk of exploding integration and management complexity. The better principles to keep in mind here are coupling and cohesion. Beware of separating closely tied use cases, that deal with similar actors, entities and data.&lt;/p&gt;
&lt;p&gt;System-level nonfunctional requirements also play a role in dividing a model into separate bounded contexts. For example, you might need to decouple the life cycle of several software components. Have them be developed, evolved, versioned and deployed independently. You might also need them to scale separately. You might even need to use completely different technology stacks, whatever is appropriate for the task at hand. This means that bounded contexts generally get implemented as individual services and/or applications. That is, as individual runtime components.&lt;/p&gt;
&lt;p&gt;The organization&amp;rsquo;s composition also plays a role when designing bounded contexts. The general rule is that a given ubiquitous language, the model it represents and the bounded context is lives in, must be owned by a single team. In software, high ownership, cohesion and consistency are desirable traits. Having a single team own and maintain a particular component foments these. Single ownership also helps reduce communication overhead, and prevents people from stepping on one another&amp;rsquo;s toes. Of course, a single team can own multiple bounded contexts, what cannot happen is one bounded context being owned by multiple teams.&lt;/p&gt;
&lt;p&gt;Indeed, in bounded contexts, we have the tools we need to make strategic decisions related to the decomposition of software systems into architecturally significant components or modules. With bounded contexts, we are able to specify the physical and ownership boundaries of these components.&lt;/p&gt;
&lt;h4 id=&#34;bounded-contexts-vs-subdomains&#34;&gt;Bounded contexts vs subdomains&lt;/h4&gt;
&lt;p&gt;Bounded contexts and subdomains are closely related concepts, but there&amp;rsquo;s one key distinction: &lt;strong&gt;subdomains&lt;/strong&gt; are discovered, while &lt;strong&gt;bounded contexts&lt;/strong&gt; are designed. Subdomains are useful because they help us understand the business strategy. Splitting the business domain into smaller problem domains is useful because it can break down a complex whole into smaller and more manageable parts.&lt;/p&gt;
&lt;p&gt;Depending on the situation, it is certainly possible to end up with a set of bounded contexts that align one-to-one with the business subdomains. However, this is not mandatory. We can develop a solution with a single bounded context that spans multiple subdomains; the same way that we can decompose the problem into many bounded contexts, some of which operate within the same particular subdomain.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/subdomains-and-bounded-contexts.png&#34; alt=&#34;Subdomains and bounded contexts&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Bounded contexts are closely related to subdomains, but aren&amp;rsquo;t tied to them. They are flexible and can be organized in many ways.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Each bounded context becomes a separate major architectural component. That is, a (micro) service, a project, an application. When we have a component that spans multiple subdomains, programming language organizational structures like namespaces or modules can be used to logically separate the subdomains within.&lt;/p&gt;
&lt;h3 id=&#34;section-4-integrating-bounded-contexts&#34;&gt;Section 4. Integrating bounded contexts&lt;/h3&gt;
&lt;p&gt;For a system to function, its components need to interact with each other. So, once we have decomposed the problem domain into separate bounded contexts, we need to decide their relationship and integration strategies. This need for interaction between them implies that there are touch points between bounded contexts. We call them &lt;strong&gt;contracts&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;These contracts are necessary because each bounded context contains its own version of the world. That is, its own model and ubiquitous language. In order to integrate, some level of translation needs to happen. They need to be adapted to one another. The contracts define these adaptations.&lt;/p&gt;
&lt;p&gt;Domain-Driven Design offers various patterns that are useful for defining contracts between bounded contexts. The decision to use one pattern vs the other depends greatly on the nature of the teams tackling the project. Depending on the teams&amp;rsquo; relationship, we can put the patterns in one of three categories: cooperation, customer-supplier, and separate ways.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/collaboration-spectrum.png&#34; alt=&#34;Collaboration spectrum&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Integration patterns are determined mainly by the level of cooperation between the teams that own the interacting bounded contexts.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&#34;cooperation-patterns&#34;&gt;Cooperation patterns&lt;/h4&gt;
&lt;p&gt;When the components that need to interact are owned by teams which are in close communication, work well together, and whose goals are aligned, &lt;strong&gt;cooperation&lt;/strong&gt; patterns can be applied.&lt;/p&gt;
&lt;p&gt;If the teams meet these criteria, a &lt;strong&gt;partnership&lt;/strong&gt; model can be implemented. This is where the integration is managed in an ad-hoc manner. Both teams work together to define the API through which their components interact and that&amp;rsquo;s that. Whenever changes happen on either side, the other team learns about it quickly and adjusts their code right away. Continuous integration is a great tool here, as breakages are immediately apparent, closing down the feedback loop.&lt;/p&gt;
&lt;p&gt;Sometimes, when different bounded contexts need to implement the same functionality, it makes more sense to develop this functionality once and package it as a reusable library, or a sub-module within a shared repository. This is what DDD calls a &lt;strong&gt;shared kernel&lt;/strong&gt;. A shared kernel is effectively a bounded context of its own, one that is statically linked to other components and implements the logic that others depend on.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/shared-kernel.png&#34; alt=&#34;Shared kernel&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A shared kernel is its own bounded context, but also &amp;ldquo;belongs&amp;rdquo; to multiple other bounded contexts.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The shared kernel integration pattern needs to be used carefully though, as it creates tight coupling between the components that use it. If the involved bounded contexts are owned by different teams, then this shared kernel that emerges violates the DDD principle of bounded contexts having single-team ownership. This is something to watch out for, as bad team synergy can produce problems during development and maintenance.&lt;/p&gt;
&lt;p&gt;When using a shared kernel, the quality of the communication and the coordination between the teams has to strike the right balance: when they aren&amp;rsquo;t strong enough to support a partnership model, but not so weak that the shared kernel would become more trouble than it&amp;rsquo;s worth.&lt;/p&gt;
&lt;p&gt;The alternative to a shared kernel is the duplication of the logic across multiple components. When deciding whether to apply this pattern, the costs of duplication vs coordination need to be considered. That is, the cost of implementing the same logic within multiple components and its subsequent changes, vs the cost of changes in the shared kernel propagating into dependent components and coordinating with the owners of each. When it is cheaper to just duplicate the logic, shared kernel should not be applied.&lt;/p&gt;
&lt;p&gt;This means that complicated models that change frequently, like those of core subdomains, are good candidates for shared kernel. Shared kernels allow complexity to be encapsulated and exposed through stable contracts. This means that frequent changes are easier to contain. Frequent changes in logic that&amp;rsquo;s highly complex and also repeated in multiple places, quickly becomes much more expensive to maintain.&lt;/p&gt;
&lt;p&gt;Another good scenario for applying a shared kernel is when refactoring a legacy monolithic system into more separated modules. The legacy system can become the shared kernel during the time that modules are being extracted from it but not yet fully decoupled.&lt;/p&gt;
&lt;h4 id=&#34;customer-supplier-patterns&#34;&gt;Customer-supplier patterns&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Customer-supplier&lt;/strong&gt; patterns establish a relationship between components where one (the provider, who is &amp;ldquo;upstream&amp;rdquo;), provides a service to another (the consumer, who is &amp;ldquo;downstream&amp;rdquo;). These types of patterns emerge when the teams who own the involved bounded contexts are not in close collaboration and have their own independent goals.&lt;/p&gt;
&lt;p&gt;One form of customer-supplier integration is the &lt;strong&gt;conformist&lt;/strong&gt; pattern. This happens when the supplier defines the integration contract/API, using its own language, concepts and model, and the consumer accepts it. This can happen when the upstream service has a well established or industry-standard model. Or maybe the model is &amp;ldquo;good enough&amp;rdquo; for the consumer to interact with directly. Organizational politics may also be a reason for this type of integration, where there is an imbalance of power favoring the supplier&amp;rsquo;s team, and they get to impose their model or can&amp;rsquo;t be bothered to adapt it.&lt;/p&gt;
&lt;p&gt;Sometimes, the consumer won&amp;rsquo;t accept the supplier&amp;rsquo;s model. In that case, an &lt;strong&gt;anticorruption layer&lt;/strong&gt; can be created. An anticorruption layer is implemented by the consumer and translates the supplier&amp;rsquo;s model into its own. This allows the consumer to use the supplier&amp;rsquo;s service without polluting its model with extraneous concepts.&lt;/p&gt;
&lt;p&gt;Anticorruption layers can be good solutions for the following scenarios:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When the consumer represents a core subdomain. The consumer is solving hard and interesting problems, so it&amp;rsquo;s best to protect its model with the ACL.&lt;/li&gt;
&lt;li&gt;When the supplier&amp;rsquo;s model is messy and inconvenient. The ACL can protect the consumer&amp;rsquo;s model from having to contend with a mess of extraneous concepts.&lt;/li&gt;
&lt;li&gt;When the supplier&amp;rsquo;s contract changes frequently. The ACL can protect the consumer from those changes, encapsulating them, allowing it to be less volatile.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A third pattern represents an anticorruption layer of sorts, only built on the supplier&amp;rsquo;s side. DDD calls this the &lt;strong&gt;open-host service&lt;/strong&gt; pattern. Here, the upstream service comes up with a new language, separate from its own, tailored to its consumers&amp;rsquo; convenience, and exposes that as its contract. This public protocol is called a &amp;ldquo;published language&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/open-host-service.png&#34; alt=&#34;Open-host service&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;An open-host service provides a protocol for consumers to interact with. It can also support multiple versions of this protocol simultaneously.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;An open-host service applies to similar scenarios as an anticorruption layer. Decoupling a service&amp;rsquo;s internal model from its integration model frees it up for continuous evolution without fear of breaking its consumers. Another advantage of this is that multiple versions of the published language can be exposed, affording clients options on what to support and gradually migrate if they so choose.&lt;/p&gt;
&lt;h4 id=&#34;separate-ways&#34;&gt;Separate ways&lt;/h4&gt;
&lt;p&gt;Sometimes, the right decision is to not integrate at all. I alluded to this outcome back when discussing the pitfalls of the shared kernel. Sometimes duplication, &lt;a href=&#34;https://refactoring.guru/smells/duplicate-code&#34;&gt;in spite of how bad it smells&lt;/a&gt;, may be the most cost effective solution to a given situation. So the teams go their &lt;strong&gt;separate ways&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This can happen when the involved teams cannot collaborate effectively for whatever reason. It could be due to geographical, timezone, or organizational issues.&lt;/p&gt;
&lt;p&gt;This can also be a good solution when the repeated logic belongs in a generic subdomain, and it&amp;rsquo;s easy to integrate. For example consider a logging framework. Exposing that kind of functionality in a service for others to consume, in most cases would be much more trouble than just including some third party library or package.&lt;/p&gt;
&lt;p&gt;It may also be that the models being integrated are just so different that they are fundamentally incompatible. It may be cost-prohibitive for collaboration or customer-supplier patterns to be applied; and duplication again, is cheaper.&lt;/p&gt;
&lt;p&gt;Going separate ways can be dangerous when we&amp;rsquo;re talking about core subdomains though. So we have to tread carefully in those scenarios. Remember that models that represent core subdomain should be implemented in the most effective and efficient ways, with few shortcuts and minimized technical debt.&lt;/p&gt;
&lt;h4 id=&#34;the-context-map&#34;&gt;The context map&lt;/h4&gt;
&lt;p&gt;The &lt;strong&gt;context map&lt;/strong&gt; can be a useful tool for high level design as it plots all the major bounded contexts (i.e. modules, components, subsystems) that we&amp;rsquo;ve designed and their interaction patterns.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/context-map.png&#34; alt=&#34;Context map&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Here&amp;rsquo;s a context map which captures the various bounded contexts that compose a big system and their interactions. The arrows point to the upstream component in the relationship. &amp;ldquo;ACL&amp;rdquo; denotes an anticorruption layer and &amp;ldquo;OHS&amp;rdquo; represents an open-host service.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Of course, they can also offer valuable insight into organizational dynamics, as team composition and relationships with others are intrinsic parts of the discussion when talking about bounded contexts. For example, it can show teams that prefer to collaborate closely or at a healthy distance. I can also show problematic components, which are surrounded by anticorruption layers or have had their ties completely cut via a separate ways approach.&lt;/p&gt;
&lt;p&gt;As with any document, they run the risk of becoming stale as the system evolves. So it should be a team-wide responsibility to keep it up to date. Each team taking care of their own components and their integration points.&lt;/p&gt;
&lt;h3 id=&#34;the-ddd-high-level-design-concept-map&#34;&gt;The DDD high level design concept map&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2026/04/high-level-system-analysis-and-design-ddd-part-1/concept-map.png&#34; alt=&#34;The DDD high level design concept map&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These are the main concepts that we&amp;rsquo;ve explored so far, and how they relate to each other.&lt;/em&gt;&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Key Takeaways from Practical Object-Oriented Design by Sandi Metz</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2024/02/key-takeaways-from-poodr/"/>
      <id>https://www.endpointdev.com/blog/2024/02/key-takeaways-from-poodr/</id>
      <published>2024-02-27T00:00:00+00:00</published>
      <author>
        <name>Kevin Campusano</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2024/02/key-takeaways-from-poodr/well-trimmed-trees.webp&#34; alt=&#34;View upward at a bright sky, with lines drawn down at an angle toward the left center by a tree trimmed into a rectangular prism and one trimmed into a vague cone. The lens is imperfect, leaving the corner of the square tree in focus while the rest of the green foliage and blue and bright white sky is somewhat distorted by the lens.&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen, 2022 --&gt;
&lt;p&gt;&lt;a href=&#34;https://www.poodr.com/&#34;&gt;Practical Object-Oriented Design: An Agile Primer Using Ruby&lt;/a&gt; by &lt;a href=&#34;https://sandimetz.com/&#34;&gt;Sandi Metz&lt;/a&gt; is one of those books that everybody who writes or aspires to write object-oriented code should read. Indeed, reading through this book will be valuable for seasoned practitioners and inexperienced novices alike. Whether it be to discover new concepts, remember why they are important, or articulate the reasons behind that warm fuzzy feeling you get in your stomach when you read well designed code, POODR can help.&lt;/p&gt;
&lt;p&gt;I personally really like this book, and here at End Point it does have quite a following as well; it was the subject of a &lt;a href=&#34;/blog/2016/08/ruby-fight-club/&#34;&gt;study group that we ran back in 2016&lt;/a&gt;. I like to dust it off every now and then to give it a re-read. To help with that, I&amp;rsquo;ve come up with a list of key takeaways from the book, with some of my own interpretations sprinkled in. For me, it serves as a sort of summary to help commit the book&amp;rsquo;s contents to memory. I thought I&amp;rsquo;d share it with you today.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While this book uses the Ruby language for its examples and discussions, the concepts it describes are equally applicable to any classical object-oriented language. Dynamically typed language users do get a little more mileage than users of statically typed ones. But still, something like 90% of the content is relevant to both. For this summary, I&amp;rsquo;ve taken care not to tie the discussion to Ruby too much and be as language agnostic as possible. I&amp;rsquo;ve chosen to write the code examples in C#.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Images taken from the book. Code taken from the book&amp;rsquo;s examples in Ruby and translated to C#.&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;chapter-1-object-oriented-design&#34;&gt;Chapter 1: Object-Oriented Design&lt;/h3&gt;
&lt;h4 id=&#34;about-design&#34;&gt;About design&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Following the principles and patterns of object-oriented design produces code that is both cost-effective and a joy to work with. &amp;ldquo;Cost effective&amp;rdquo; means that it doesn&amp;rsquo;t take more effort than necessary to evolve, to change.&lt;/li&gt;
&lt;li&gt;The reason design is important is because software changes. A good design is one that makes software easy to change.&lt;/li&gt;
&lt;li&gt;Object-oriented design sees the world as a collection of parts that interact with each other. The parts we call &amp;ldquo;objects&amp;rdquo;, and the interactions we call &amp;ldquo;messages&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;In order to send messages to each other, objects need to have some knowledge about one another. This knowledge produces &amp;ldquo;dependencies&amp;rdquo; between them.&lt;/li&gt;
&lt;li&gt;Managing these dependencies is a big part of object-oriented design. OOD aims to create dependencies in such a way that they don&amp;rsquo;t make the process of changing objects too difficult.&lt;/li&gt;
&lt;li&gt;Design is important no matter the size of the application. Because both small and large applications change. And change is what design allows. A badly designed small application will eventually become a badly designed large one.&lt;/li&gt;
&lt;li&gt;Design is the way in which code is arranged. Good design is an arrangement of code that makes change easy.&lt;/li&gt;
&lt;li&gt;Our job as developers is to take our application&amp;rsquo;s requirements and our knowledge of design principles and use them to produce code that is cost effective today and tomorrow: code that is easy to change.&lt;/li&gt;
&lt;li&gt;The idea is not to predict future changes. Instead, we have to accept that change will come and prepare for it. We prepare for it by writing code that leaves our options open for the future.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The purpose of design is to allow you to design later, and its primary goal is to reduce the cost of change.&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;failures-of-design&#34;&gt;Failures of design&lt;/h4&gt;
&lt;ol start=&#34;11&#34;&gt;
&lt;li&gt;&lt;strong&gt;Design fails when you don&amp;rsquo;t do it.&lt;/strong&gt; Code bases that lack in design will eventually evolve into unmaintainable messes, where change becomes increasingly hard even for the most minor new requirements. &amp;ldquo;Throwing everything away and beginning from scratch&amp;rdquo; becomes a viable alternative.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Design fails when you overdesign.&lt;/strong&gt; Armed with basic design skills, it&amp;rsquo;s easy to fall into the trap of developing wrong abstractions, applying principles incorrectly, seeing the wrong pattern in the wrong context. Applications that suffer from overdesign become gigantic castles of code full of indirection that become hard to change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Design fails when you separate it from programming.&lt;/strong&gt; Design is best executed as an iterative and incremental process with a quick feedback loop. The design needs to be adjusted frequently, as understanding of the domain changes. Design that is dictated to programmers from on high as part of a &amp;ldquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Big_design_up_front&#34;&gt;Big Up Front Design&lt;/a&gt;&amp;rdquo; is doomed to failure. Such arrangements are not agile enough to be resilient to requirement changes.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;agile-and-design&#34;&gt;Agile and design&lt;/h4&gt;
&lt;ol start=&#34;14&#34;&gt;
&lt;li&gt;Agile development says: &amp;ldquo;Avoid Big Up Front Design because you can&amp;rsquo;t know what the application will end up being because requirements always change and they do so often.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Agile also says: &amp;ldquo;Good design is essential. Because change comes often, your code needs to be ready to accommodate those changes in an efficient and cost effective way.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Design is not a &amp;ldquo;one time at the beginning of the project&amp;rdquo; type of task. It is an ongoing, iterative and incremental task that happens as requirements change, and as our domain knowledge and skills increase.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;metrics&#34;&gt;Metrics&lt;/h4&gt;
&lt;ol start=&#34;17&#34;&gt;
&lt;li&gt;Bad object-oriented design metrics are an indicator of a bad design. But good metrics are not an indicator of good design. A code base with bad metrics will most likely be hard to change.&lt;/li&gt;
&lt;li&gt;The ideal software metric would be &amp;ldquo;&lt;strong&gt;cost per feature per time interval&lt;/strong&gt;&amp;rdquo;. But this is nigh on impossible to calculate because &amp;ldquo;cost&amp;rdquo;, &amp;ldquo;feature&amp;rdquo;, and &amp;ldquo;time interval&amp;rdquo; are in most cases nebulous concepts.&lt;/li&gt;
&lt;li&gt;Still, &amp;ldquo;cost per feature per time interval&amp;rdquo; tells us that our goal should always be to write code with a low cost per feature. Making sure that it is also low cost to evolve in the future.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;technical-debt&#34;&gt;Technical debt&lt;/h4&gt;
&lt;ol start=&#34;20&#34;&gt;
&lt;li&gt;&lt;strong&gt;Technical debt&lt;/strong&gt; is borrowing time from the future. That is, putting out a bad design today in order to release a feature quickly. Tomorrow, when change comes, the bad design will prevent cost effective change. So time will have to be spent refactoring, turning the bad design into a good one. If refactoring doesn&amp;rsquo;t happen, the debt increases, making future changes more and more expensive.&lt;/li&gt;
&lt;li&gt;How much design you do depends on your skill and your time frame. You can&amp;rsquo;t do so much design that it prevents you from delivering on time. Design is an investment, and for an investment to be good, it needs to return some profit. Good design&amp;rsquo;s returns are quick and plentiful.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The trick to getting the most bang for your design buck is to acquire an understanding of the theories of design and to apply them appropriately, at the right time, and in the right amounts.&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;chapter-2-designing-classes-with-a-single-responsibility&#34;&gt;Chapter 2: Designing Classes with a Single Responsibility&lt;/h3&gt;
&lt;h4 id=&#34;about-classes&#34;&gt;About classes&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Classes&lt;/strong&gt; are the most basic organizational structure of object-oriented systems written with class-based object-oriented languages. As such, that&amp;rsquo;s the first thing that we focus on when designing such systems.&lt;/li&gt;
&lt;li&gt;Your first instinct should be to keep things simple. Use classes to model only the features that your application needs today and make sure that they are easy to change tomorrow.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Design is more the art of preserving changeability than it is the act of achieving perfection.&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;write-code-that-is-true&#34;&gt;Write code that is TRUE&lt;/h4&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;In order to be easy to change, code should be &lt;strong&gt;TRUE&lt;/strong&gt;:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code should be &amp;ldquo;Transparent&amp;rdquo;.&lt;/strong&gt; It should be easy to tell what will be the consequences of changing the code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code should be &amp;ldquo;Reasonable&amp;rdquo;.&lt;/strong&gt; The cost of a change should be proportional to the size of the requirement that provoked the change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code should be &amp;ldquo;Usable&amp;rdquo;.&lt;/strong&gt; The code should be easy to reuse in situations other than the one it&amp;rsquo;s currently being used in.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code should be &amp;ldquo;Exemplary&amp;rdquo;.&lt;/strong&gt; The code should exhibit qualities that guide and/or encourage those who change it to keep and replicate those qualities.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Single_responsibility_principle&#34;&gt;Single Responsibility Principle&lt;/a&gt; is a prerequisite to creating code that is TRUE.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;single-responsibility&#34;&gt;Single Responsibility&lt;/h4&gt;
&lt;ol start=&#34;10&#34;&gt;
&lt;li&gt;A class should have one single responsibility. That means that it needs to do one thing and do it well. It needs to be as small as possible and fulfill a single purpose. It needs to have only one reason to change.&lt;/li&gt;
&lt;li&gt;A good way to identify what classes your system needs is to read through your user stories or problem descriptions and identify &lt;strong&gt;nouns&lt;/strong&gt;. Those nouns are good candidates for classes.&lt;/li&gt;
&lt;li&gt;If there are &lt;strong&gt;verbs&lt;/strong&gt; and &lt;strong&gt;properties&lt;/strong&gt; associated with those nouns, then it is most likely a class. Because classes represent bundles of both data (attributes) and behavior (methods).&lt;/li&gt;
&lt;li&gt;Classes that have many responsibilities are hard to reuse. And because they are not &amp;ldquo;Usable&amp;rdquo;, they are not easy to change.&lt;/li&gt;
&lt;li&gt;A class that has many responsibilities usually has unrelated code tangled together within it. This makes the class hard to reason about, and hard to reuse.&lt;/li&gt;
&lt;li&gt;In order to reuse the behavior defined within a class with multiple tangled responsibilities, you either need to duplicate code or use the entire class, even the parts that you don&amp;rsquo;t need.&lt;/li&gt;
&lt;li&gt;If you use a class that has many reasons to change, when something unrelated to your use case changes, you will still have to change your code. This is unexpected and surprising. This is not &amp;ldquo;Transparent&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Depending on classes that have many responsibilities increases the chances of your application breaking.&lt;/li&gt;
&lt;li&gt;A good way to determine whether a class has a single responsibility is to try to enunciate what it does in a single sentence. That sentence should be simple, because classes should be simple. Look out for the words &amp;ldquo;and&amp;rdquo; and &amp;ldquo;or&amp;rdquo; in this sentence, as they point to it having more than one responsibility.&lt;/li&gt;
&lt;li&gt;Another good way to determine whether a class has a single responsibility is thinking about every one of its methods as a question that the class would be able to respond to if it were a sentient being. For example: &amp;ldquo;Array, what is your length?&amp;rdquo; If the question doesn&amp;rsquo;t make sense, then maybe the method does not belong in the class.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cohesion&lt;/strong&gt; is the measure of how related to their core purpose the elements of a component are. Classes that have a single responsibility are highly cohesive because all of their parts work towards a single goal.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;when-to-make-design-decisions&#34;&gt;When to make design decisions&lt;/h4&gt;
&lt;ol start=&#34;21&#34;&gt;
&lt;li&gt;Only design as much as you need to for right now. Don&amp;rsquo;t make design decisions prematurely. Sometimes waiting for more information before committing to a design is the way to go. More information in the future will often reveal a better design.&lt;/li&gt;
&lt;li&gt;Consider postponing design decisions when the information available to you today does not point clearly to a good design. Also, when the cost of not doing it now does not considerably make tomorrow&amp;rsquo;s change more expensive.&lt;/li&gt;
&lt;li&gt;On the other hand, consider that a class that&amp;rsquo;s left in a &amp;ldquo;bad state&amp;rdquo; may be reused by others, making their code depend on badly designed code. The application will suffer as a result.&lt;/li&gt;
&lt;li&gt;The structure of a class is supposed to reveal your design&amp;rsquo;s intention to other developers. When it doesn&amp;rsquo;t, when it is not &amp;ldquo;Exemplary&amp;rdquo;, then future maintenance costs increase.&lt;/li&gt;
&lt;li&gt;The tension between &amp;ldquo;improve it now&amp;rdquo; and &amp;ldquo;improve it later&amp;rdquo; is always present. Our job as designers is to strike a good balance &amp;ldquo;between the needs of the present and the possibilities of the future&amp;rdquo; so that the costs of change are kept low.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;techniques-for-writing-code-thats-easy-to-change&#34;&gt;Techniques for writing code that&amp;rsquo;s easy to change&lt;/h4&gt;
&lt;ol start=&#34;26&#34;&gt;
&lt;li&gt;&lt;strong&gt;Depend on behavior, not data: hide instance variables.&lt;/strong&gt; Instead of accessing instance variables directly, use accessor methods. Even from within the class that owns them. &amp;ldquo;Always send messages to access data.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;That way you consolidate the knowledge of what the data represents in a single place. That&amp;rsquo;s the Single Responsibility Principle in action. Changing it becomes easy as a result because instead of changing references to a variable in potentially multiple places; you only need to change the definition of a method, in a single location.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Depend on behavior, not data: hide data structures.&lt;/strong&gt; When code depends on or receives as input a complex data structure like a big array or hash, encapsulate the data structure in a class with a clear interface, instead of accessing and manipulating the structure directly.&lt;/li&gt;
&lt;li&gt;Directly manipulating complex data structures is a style of coding that tends to propagate. If the incoming data structure changes, even slightly, then a lot of your code also needs to change because it depends on its very particular structure.&lt;/li&gt;
&lt;li&gt;Handling complex raw data structures through classes and messages with clear, intention-revealing names demystifies the structure and gives it meaning within the context of the application domain.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, instead of this&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ObscuringReferences&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt;[][] data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; ObscuringReferences(&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt;[][] data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;.data = data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; IEnumerable&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt;&amp;gt; GetDiameters()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; data.Select(cell =&amp;gt; cell[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;] + (cell[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;] * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;hellip;do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;RevealingReferences&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IEnumerable&amp;lt;Wheel&amp;gt; Wheels { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; RevealingReferences(&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt;[][] data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Wheels = Wheelify(data);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// This method is now more readable.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; IEnumerable&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt;&amp;gt; GetDiameters()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Wheels.Select(wheel =&amp;gt; wheel.Rim + (wheel.Tire * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// Now everyone can send rim/tire to wheel.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;record&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Wheel&lt;/span&gt;(&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; Rim, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; Tire);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; IEnumerable&amp;lt;Wheel&amp;gt; Wheelify(&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt;[][] data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; data.Select(cell =&amp;gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Wheel(cell[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;], cell[&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;]));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol start=&#34;31&#34;&gt;
&lt;li&gt;&lt;strong&gt;Enforce single responsibility everywhere: extract extra responsibilities from methods.&lt;/strong&gt; Methods should also have a single responsibility. Just like classes, that makes them easy to reuse, change, and understand.&lt;/li&gt;
&lt;li&gt;To determine if a method has a single responsibility, the same techniques that work for classes apply. Try to enunciate their purpose in a single sentence, and ask them what they do.&lt;/li&gt;
&lt;li&gt;Methods that iterate on items and act upon them too are a common case of multiple responsibilities. Separating iteration and action into two methods is a common refactoring to correct it.&lt;/li&gt;
&lt;li&gt;Complex calculations embedded within methods are also good candidates to be separated into other methods. It gives them a name and makes them reusable.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, instead of this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IEnumerable&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt;&amp;gt; GetDiameters()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Wheels.Select(wheel =&amp;gt; wheel.Rim + (wheel.Tire * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;hellip;do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// First - iterate over the collection.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IEnumerable&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt;&amp;gt; _GetDiameters()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Wheels.Select(wheel =&amp;gt; GetDiameter(wheel));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// Second - calculate diameter of ONE wheel.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; GetDiameter(Wheel wheel)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; wheel.Rim + (wheel.Tire * &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol start=&#34;35&#34;&gt;
&lt;li&gt;These refactorings are useful and necessary even when you don&amp;rsquo;t know what the final design will look like. In fact, these refactorings (and good practices like these) will often reveal the final design.&lt;/li&gt;
&lt;li&gt;Small methods with a single responsibility have many benefits. They make a class&amp;rsquo;s details, features, and components more obvious, they are self-documenting, encourage reuse, establish a style of programming that is self-perpetuating, become easy to move to another class when and if that time comes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enforce single responsibility everywhere: isolate extra responsibilities in classes.&lt;/strong&gt; Move the responsibilities that are extraneous to a class into another class. If you can afford it, create a separate class to hold them. If not, at least encapsulate them in an embedded class so that they are contained and don&amp;rsquo;t leak.&lt;/li&gt;
&lt;li&gt;Embedded classes say: This class only has meaning and value when thought about within the context of this other class.&lt;/li&gt;
&lt;li&gt;Embedded classes can be easily promoted to independent classes later if the need arises.&lt;/li&gt;
&lt;li&gt;Once all methods inside a class have a single responsibility and are each doing the smallest useful thing, it becomes easier to identify the features that may belong to another class.&lt;/li&gt;
&lt;li&gt;The purpose of design is not to produce &amp;ldquo;perfect&amp;rdquo; code but instead to produce code that&amp;rsquo;s &amp;ldquo;good enough&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;The Single Responsibility Principle &amp;ldquo;allows change without consequence and reuse without duplication&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;chapter-3-managing-dependencies&#34;&gt;Chapter 3: Managing Dependencies&lt;/h3&gt;
&lt;h4 id=&#34;about-dependencies&#34;&gt;About dependencies&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Objects should have a single responsibility and do the smallest useful thing. This means that, in order to fulfill complex application requirements, objects need to collaborate with one another.&lt;/li&gt;
&lt;li&gt;Objects collaborate by knowing things about and sending messages to each other. That creates &lt;strong&gt;dependencies&lt;/strong&gt;. A good design manages these dependencies, making sure they don&amp;rsquo;t couple objects so much that change becomes painful.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coupling&lt;/strong&gt; measures how much interdependency exists between software components. High coupling makes things hard to change.&lt;/li&gt;
&lt;li&gt;An object has a dependency when it knows &lt;strong&gt;the name of another class&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;An object has a dependency when it knows &lt;strong&gt;the name of a method from another class&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;An object has a dependency when it knows &lt;strong&gt;the arguments of that method&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;An object has a dependency when it knows &lt;strong&gt;the order of those arguments&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Dependencies create a situation where if an object changes, then other objects that depend on it may be forced to change as well.&lt;/li&gt;
&lt;li&gt;Dependencies couple objects to each other. Highly coupled objects behave as if they were a unit. It becomes hard to reuse one without the other. If not managed properly, dependencies will disseminate and entangle the entire code base.&lt;/li&gt;
&lt;li&gt;Some dependencies are unavoidable. So the purpose of design is to reduce and contain dependencies. Ensure objects only have the minimum number of dependencies that they need to do their jobs. Keep the essential ones, remove the rest.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;techniques-for-writing-loosely-coupled-code&#34;&gt;Techniques for writing loosely coupled code&lt;/h4&gt;
&lt;ol start=&#34;11&#34;&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Dependency_injection&#34;&gt;&lt;strong&gt;Dependency injection&lt;/strong&gt;&lt;/a&gt;. It can help eliminate dependencies on concrete classes. Instead of instantiating new objects of another class inside your object, let the object receive it as a constructor or method parameter. The object&amp;rsquo;s users can do the instantiation.&lt;/li&gt;
&lt;li&gt;An object that knows less can often times do more. The knowledge of how to instantiate a particular object limits its potential. Object creation and utilization don&amp;rsquo;t need to be contained within the same unit of code.&lt;/li&gt;
&lt;li&gt;When an object hard-codes the reference to a class, it advertises that it can&amp;rsquo;t work with any other type. Replace the reference to the concrete class with an abstraction (e.g. an &lt;a href=&#34;https://en.wikipedia.org/wiki/Interface_(object-oriented_programming)&#34;&gt;interface&lt;/a&gt; or &lt;a href=&#34;https://en.wikipedia.org/wiki/Duck_typing&#34;&gt;duck type&lt;/a&gt;). That gives it the flexibility to be able to collaborate with other objects that respond to the same messages.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;With dependency injection you can turn this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Gear&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;float&lt;/span&gt; Ratio { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; Rim { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; Tire { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; Gear(&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;float&lt;/span&gt; ratio, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; rim, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; tire)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Ratio = ratio;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Rim = rim;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Tire = tire;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;float&lt;/span&gt; GetGearInches()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Ratio * &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Wheel(Rim, Tire).GetDiameter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Into this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Gear&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;float&lt;/span&gt; Ratio { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Wheel Wheel { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// Instead of rim and tire, Gear&amp;#39;s constructor now receives a wheel.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; Gear(&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;float&lt;/span&gt; ratio, Wheel wheel)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Ratio = ratio;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Wheel = wheel;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;float&lt;/span&gt; GetGearInches()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;// Instead of creating a new wheel, it uses the one that&amp;#39;s been injected.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Ratio * Wheel.GetDiameter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol start=&#34;14&#34;&gt;
&lt;li&gt;Sometimes it is not possible to remove a dependency from an object. In those cases, your best bet is to isolate it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Isolate dependencies: isolate instance creation&lt;/strong&gt;. Sometimes it is not possible to apply dependency injection. In those cases, the next best thing is to encapsulate instantiation of external classes into their own methods.&lt;/li&gt;
&lt;li&gt;An instantiation encapsulated in a method allows the code to clearly and explicitly communicate that there&amp;rsquo;s an extraneous dependency here. One that we&amp;rsquo;d like to remove but for now cannot. We also protect the class from that dependency propagating through it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Isolate dependencies: isolate vulnerable external messages&lt;/strong&gt;. The same technique can be applied to invocations of methods on external classes. Encapsulate such calls into their own methods in order to contain the dependency.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&amp;rsquo;s what isolating some dependencies could look like. From this&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;float&lt;/span&gt; GetGearInches()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Ratio * &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Wheel(Rim, Tire).GetDiameter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;hellip;to this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;float&lt;/span&gt; GetGearInches()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; Ratio * GetWheelDiameter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// The dependency on the Wheel class is isolated in this method.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;int&lt;/span&gt; GetWheelDiameter()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Wheel(Rim, Tire).GetDiameter();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol start=&#34;18&#34;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reduce argument dependencies: use keyword arguments&lt;/strong&gt;. If your language supports them, keyword arguments are a great way of reducing the dependency incurred via method invocations. They allow the parameters to be sent in any order, which means that changes to the method&amp;rsquo;s definition and signature are less likely to cause the callers to have to also change. Also, they have a self-documenting property on both caller and callee. (See &lt;a href=&#34;https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments&#34;&gt;named arguments in C#&lt;/a&gt; and &lt;a href=&#34;https://thoughtbot.com/blog/ruby-2-keyword-arguments&#34;&gt;keyword arguments in Ruby&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reduce argument dependencies: explicitly define defaults&lt;/strong&gt;. If your language has the feature, parameter defaults are a great way of reducing dependencies to method parameters, as establishing a default for a parameter makes it optional.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reduce argument dependencies: isolate multiparameter initialization&lt;/strong&gt;. If you don&amp;rsquo;t own the code for a complex object initialization or method invocation, you can always encapsulate it in an object or method of your own. It can be done with a thin wrapper that exposes an interface that follows the techniques we&amp;rsquo;ve discussed and that uses the language of your application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Classes should depend on things that change less often than they do.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There are three truths about code related to change and dependencies:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;ldquo;Some classes are more likely to change than others&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Concrete classes are more likely to change than abstract classes&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Changing a class that has many dependents will have many consequences&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&amp;rsquo;s OK to depend on classes with a low likelihood of change. For example, classes in the built-in library of your language generally will change less than your own custom classes. Framework classes commonly change less often too, but that may not always be the case if you framework is new or rapidly evolving.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Abstractions are generally much more stable than concretions. Because of this, &lt;strong&gt;it is safer to depend on abstract classes&lt;/strong&gt; (e.g. interfaces and duck types) than on concrete ones.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Avoid classes that have lots of dependencies. Any changes done to them produce a ripple effect of changes throughout the code base. Also, because of that, people will go through great lengths to try to avoid changing them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When thinking about dependents and likelihood of change, &lt;strong&gt;the following are harmless&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Classes with few dependents and low likelihood of change (e.g. specialized infrastructure interaction classes).&lt;/li&gt;
&lt;li&gt;Classes with few dependents and high likelihood of change (e.g. concrete classes that implement your app&amp;rsquo;s domain logic).&lt;/li&gt;
&lt;li&gt;Classes with many dependents and low likelihood of change (e.g. interfaces and other abstractions).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When thinking about dependents and likelihood of change, &lt;strong&gt;the following is harmful&lt;/strong&gt;: Classes with many dependents and high likelihood of change (e.g. concrete classes that are used throughout the code base).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2024/02/key-takeaways-from-poodr/likelihood-of-change-versus-number-of-dependents.webp&#34; alt=&#34;A graph divided into four cells. The y axis is labeled &amp;ldquo;dependents&amp;rdquo;, from Few to Many. The x axis is labeled &amp;ldquo;Likelihood of requirements change&amp;rdquo;, from Less to More. The cell with less likelihood of requirements change and many dependents reads &amp;ldquo;Abstract Zone: Changes are unlikely but, if they occur, will have broad effects.&amp;rdquo; The cell with less likelihood of requirements change and fewer dependents reads &amp;ldquo;Neutral Zone: Changes are unlikely and have few side effects.&amp;rdquo; The cell with more likelihood of requirements change and few dependents reads &amp;ldquo;Neutral Zone: Changes are likely but they have few side effects.&amp;rdquo; The cell with more likelihood of requirements change and many dependents reads &amp;ldquo;Danger Zone: These classes WILL change and the changes will cascade into dependents.&amp;rdquo;&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;chapter-4-creating-flexible-interfaces&#34;&gt;Chapter 4: Creating Flexible Interfaces&lt;/h3&gt;
&lt;h4 id=&#34;about-interfaces&#34;&gt;About interfaces&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;The messages that objects pass between each other are a big concern for design. In addition to what objects know (responsibilities), and who they know (dependencies), design cares about how they talk to one another. Messages pass between objects through their interfaces.&lt;/li&gt;
&lt;li&gt;In a well designed application, the messages that pass between objects follow a pattern that&amp;rsquo;s closer to the diagram on the right than that of the diagram on the left:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2024/02/key-takeaways-from-poodr/communication-patterns.webp&#34; alt=&#34;On the left, many dots are connected by a complex network of single-direction arrows. Dots have several arrows pointing to and from them. On the right, the same dots are connected by a single arrow to each. Each dot either has one or more arrows pointing away from it, or a single arrow pointing to it.&#34;&gt;&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;Objects that expose too much of themselves and know too much about others are hard to reuse and make systems hard to change.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Objects that minimize what they expose of themselves and know little about others are easily reusable and changeable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;An object&amp;rsquo;s &lt;strong&gt;public interface&lt;/strong&gt; is the set of messages that it responds to. That is, the set of methods that other objects are welcome to invoke. Good design calls for objects with clear and concise public interfaces.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Classes should have one responsibility, but they will likely have many methods. Some methods are more general and expose the main features of a class; they are the services that the class offers its callers. These should make up the class&amp;rsquo;s public interface. Other methods are more specific, serve to support those features, and contain implementation details internal to the class and uninteresting to callers. These make up the class&amp;rsquo;s private interface.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The methods in a class&amp;rsquo;s public interface&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;ldquo;Reveal its primary responsibility&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Are expected to be invoked by others&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Are not likely to change&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Are safe for others to depend on&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Are directly covered by tests&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The methods in a class&amp;rsquo;s private interface&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;ldquo;Handle implementation details&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Are not expected to be invoked by other objects&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Are likely to change&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Are unsafe for others to depend on&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;May not even be referenced in the tests&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Public methods list the specific features of a class that allow it to fulfill its responsibility. They advertise to the world what the purpose of the class they belong to is.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Public methods are stable and are expected to not change often, so others are welcome to depend on them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Private methods are not stable at all. They are hidden from others so nobody should depend on them.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;discovering-less-obvious-objects-and-messages&#34;&gt;Discovering less obvious objects and messages&lt;/h4&gt;
&lt;ol start=&#34;12&#34;&gt;
&lt;li&gt;When analyzing a problem domain, the nouns in the narrative usually become your first classes. These are called &amp;ldquo;&lt;strong&gt;domain objects&lt;/strong&gt;&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t let domain objects be your only classes, though. Shift your focus toward messages and away from classes to discover new, less obvious objects that will implement key functionality. Not doing so will risk overloading your domain objects with more responsibility than what they can handle.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Sequence_diagram&#34;&gt;UML sequence diagrams&lt;/a&gt; are an excellent way to explore design alternatives. You can use them to draft objects and their interactions, i.e. the messages they send each other. They are quick, low cost, and allow easy communication of ideas between team members. Here&amp;rsquo;s an online tool that generates them based on plain text: &lt;a href=&#34;https://sequencediagram.org/&#34;&gt;sequencediagram.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The transition from class-based design to message-based design is one that yields more flexible applications. It means asking &amp;ldquo;I need to send this message, who should respond to it?&amp;rdquo; instead of &amp;ldquo;I know I need this class, what should it do?&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;focusing-on-what-instead-of-how&#34;&gt;Focusing on &amp;ldquo;what&amp;rdquo; instead of &amp;ldquo;how&amp;rdquo;&lt;/h4&gt;
&lt;ol start=&#34;16&#34;&gt;
&lt;li&gt;Public methods should focus on &amp;ldquo;what&amp;rdquo; instead of &amp;ldquo;how&amp;rdquo;. That is, they should express what the caller wants instead of how the callee must behave.&lt;/li&gt;
&lt;li&gt;If you&amp;rsquo;re in a situation where an object calls many methods on another in succession, try to refactor so that all the logic is executed as a result of a single message. This consolidation reduces the size of the second object&amp;rsquo;s public interface, which reduces what callers need to know about it, which reduces dependency, which makes change easier. The caller only knows &amp;ldquo;what&amp;rdquo; it needs, not &amp;ldquo;how&amp;rdquo; to make the callee deliver.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;When focusing on &amp;ldquo;what&amp;rdquo; instead of &amp;ldquo;how&amp;rdquo;, code like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Trip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IEnumerable&amp;lt;Bicycle&amp;gt; Bicycles { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Mechanic Mechanic { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; Prepare()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; bike &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;in&lt;/span&gt; Bicycles)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Mechanic.CleanBicyble(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Mechanic.PumpTires(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Mechanic.LubeChain(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Mechanic.CheckBrakes(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Mechanic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; CheckBrakes(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; CleanBicyble(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; LubeChain(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PumpTires(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Can be transformed into code like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Trip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    IEnumerable&amp;lt;Bicycle&amp;gt; Bicycles { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Mechanic Mechanic { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// This method was greatly simplified and its dependencies were reduced.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; Prepare()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; bike &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;in&lt;/span&gt; Bicycles)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Mechanic.PrepareBicycle(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Mechanic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareBicycle(Bicycle bike)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CleanBicyble(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PumpTires(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LubeChain(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CheckBrakes(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// Notice how Mechanic&amp;#39;s public interface was reduced considerably.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// All of these methods are private now.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; CheckBrakes(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; CleanBicyble(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; LubeChain(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PumpTires(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;h4 id=&#34;liberate-objects-from-their-context&#34;&gt;Liberate objects from their context&lt;/h4&gt;
&lt;ol start=&#34;18&#34;&gt;
&lt;li&gt;An object&amp;rsquo;s context is made up of the things that an object knows about others. What other objects it calls and how. What it needs in order to be able to work.&lt;/li&gt;
&lt;li&gt;A good design tries to allow objects to work with minimal context. &amp;ldquo;Objects that have a simple context are easy to use and easy to test; they expect few things from their surroundings. Objects that have a complicated context are hard to use and hard to test; they require complicated setup before they can do anything&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;In order to reduce context, we need to reduce the knowledge that callers have about the other components they call. A simple public interface helps with that. In practical terms that means fewer and less verbose methods, fewer parameters, fewer dependencies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Objects need to trust their collaborators to do their part&lt;/strong&gt;. Focusing on what the caller wants instead of what the callee does is a way of keeping context in check. This allows objects to collaborate with others regardless of what type they are and what they do.&lt;/li&gt;
&lt;li&gt;Dependency injection is a mechanism through which objects can collaborate with others when they don&amp;rsquo;t know their type. A dependency injected via parameter (declared as an interface or duck type) hides its identity from its user.&lt;/li&gt;
&lt;li&gt;Naming the methods of this injected dependency from the perspective of the caller reveals a generic interface that offers the features that the caller wants in the vocabulary that it understands. The caller does not need to know what the injected dependency does, only what it needs it to do.&lt;/li&gt;
&lt;li&gt;Highly coupled objects with verbose public interfaces say to their collaborators: &amp;ldquo;I know what I want, and I know how you do it&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;More decoupled objects with concise public interfaces say to their collaborators: &amp;ldquo;I know what I want, and I know what you do&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Highly decoupled objects with concise public interface and minimal required context say to their collaborators: &amp;ldquo;I know what I want, and I trust you to do your part&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;When objects trust their collaborators, and focus on what they want instead of what others do, the previous Trip/​Mechanic example can become like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Trip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; IEnumerable&amp;lt;Bicycle&amp;gt; Bicycles { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Mechanic Mechanic { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; Prepare()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888&#34;&gt;// Trip now fully trusts Mechanic, and doesn&amp;#39;t even know what it does.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Mechanic.PrepareTrip(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Mechanic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// The knowledge of &amp;#34;how a mechanic prepares a trip&amp;#34; now completely lives&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// within Mechanic.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareTrip(Trip trip)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; bike &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;in&lt;/span&gt; trip.Bicycles)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            PrepareBicycle(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareBicycle(Bicycle bike)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CleanBicyble(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PumpTires(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        LubeChain(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CheckBrakes(bike);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; CheckBrakes(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; CleanBicyble(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; LubeChain(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PumpTires(Bicycle bike) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;h4 id=&#34;rules-of-thumb-for-writing-code-with-good-interfaces&#34;&gt;Rules of thumb for writing code with good interfaces&lt;/h4&gt;
&lt;ol start=&#34;27&#34;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create explicit interfaces&lt;/strong&gt;. Be intentional and obvious when defining public and private methods. Use your language access modifiers (i.e. public, private, protected, etc). Your public methods should:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Be explicitly identified as such&lt;/li&gt;
&lt;li&gt;Be more about what than how&lt;/li&gt;
&lt;li&gt;Have names that are unlikely to change&lt;/li&gt;
&lt;li&gt;Use keyword arguments&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Respect the public interface of others&lt;/strong&gt;. Invoke only public methods on the classes that you use. Avoid circumventing their public interfaces and directly calling private members. Depending on the private interface of framework and library classes is like a ticking time bomb. The reason they are private is because they are expected to change or disappear entirely.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Minimize context&lt;/strong&gt;. Focus on &amp;ldquo;what&amp;rdquo; instead of &amp;ldquo;how&amp;rdquo; when designing public interfaces. Favor public methods that allow callers to access your classes&amp;rsquo; functionality without having to know how they do it. Use interface and duck types to name methods from the perspective of and with the vocabulary of the callers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you have to interact with a class that does not have a clean interface, and you don&amp;rsquo;t own it or otherwise can&amp;rsquo;t refactor it so that it does, isolate it. Use the same techniques for dependency isolation mentioned in Chapter 3. Wrap the invocation in a new class or method to contain it and give that wrapper a clean public interface.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Follow the law of Demeter&lt;/strong&gt;. The law of Demeter states that you shouldn&amp;rsquo;t chain multiple method calls that navigate across many different types of objects. In other words &amp;ldquo;talk only to your close neighbors&amp;rdquo; or &amp;ldquo;use only one dot&amp;rdquo;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Violations ot the law of Demeter look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;customer.GetBicycle().Wheel.Rotate();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol start=&#34;32&#34;&gt;
&lt;li&gt;Violations of the law of Demeter make for code that&amp;rsquo;s not TRUE. Changes in the object at the end of the chain ripple through the entire chain. This is unexpected and laborious, making the code neither Transparent nor Reasonable. The class that uses the chain depends on all the objects in the chain, making it non-Usable. These chains are easy to replicate and harm changeability, making the code not Exemplary.&lt;/li&gt;
&lt;li&gt;Always evaluate the cost of violating the law of Demeter versus the cost of abiding by it. Method chains that ultimately read an attribute are generally less harmful. Also, method chains on really stable classes like those of your language library or framework have low impact.&lt;/li&gt;
&lt;li&gt;Delegation can appear to be a solution to law of Demeter violations. Unfortunately, all it does is remove the evidence that it&amp;rsquo;s there.&lt;/li&gt;
&lt;li&gt;In reality, a violation to the law of Demeter indicates that there&amp;rsquo;s an object missing or that the public interface of an object is lacking. Find the object, and its interface, by thinking more about messages and less about classes. Define the interface by thinking about what the object needs of its collaborators, and not about how it can get it by itself.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;chapter-5-reducing-costs-with-duck-typing&#34;&gt;Chapter 5: Reducing Costs with Duck Typing&lt;/h3&gt;
&lt;h4 id=&#34;about-duck-types&#34;&gt;About duck types&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Duck types&lt;/strong&gt; are public interfaces that manifest themselves across classes. When multiple classes accept the same messages (i.e. define methods with the same signature), they are said to be of the same duck type.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Duck type&amp;rdquo; is a dynamic language concept. Static languages offer equivalent features via &amp;ldquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Interface_(object-oriented_programming)&#34;&gt;interfaces&lt;/a&gt;&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;The difference is that, in statically typed languages, interfaces need to be explicitly defined in code and concrete classes need to explicitly implement them. On the other hand, duck types in dynamically typed languages need only be acknowledged in an abstract sense. They don&amp;rsquo;t have to be explicitly defined in code.&lt;/li&gt;
&lt;li&gt;Duck types and interfaces establish a contract. A set of messages that a given object is expected to be able to receive. A protocol that users of these objects can be confident that they will adhere to.&lt;/li&gt;
&lt;li&gt;Just as a class can implement multiple interfaces, an object can be of many duck types. That&amp;rsquo;s because interfaces and duck types materialize depending on the situation in which objects that implement them are used. The same object can be used in different places for different things. Each user will see the object from their own perspective, and each can expect it conform to a different interface. See the &lt;a href=&#34;https://en.wikipedia.org/wiki/Interface_segregation_principle&#34;&gt;interface segregation principle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Moreover, code that depends on an interface or duck type is flexible enough to collaborate with any concrete class that implements that interface or duck type. See the &lt;a href=&#34;https://en.wikipedia.org/wiki/Liskov_substitution_principle&#34;&gt;Liskov substitution principle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;As we&amp;rsquo;ve established, it&amp;rsquo;s better to depend on abstractions than to depend on concretions. So, users of an object should not care what its type is, only what it does. Behavior over identity. In other words, they should focus on messages and public interfaces, instead of specific classes. Duck types and interfaces bring to the forefront what an object does and abstracts away what it is.&lt;/li&gt;
&lt;li&gt;Applying duck types to a situation makes the code more abstract and less concrete. Concrete code is easier to understand but harder to extend. Abstract code is harder to understand at the beginning but easier to change. In the long run, abstract code tends to reduce maintenance costs.&lt;/li&gt;
&lt;li&gt;When an object invokes methods on multiple objects in order to achieve a single purpose, that&amp;rsquo;s a situation where a duck type may be helpful. Think from the perspective of the caller and what it needs to come up with a message that makes sense for it to send its many collaborators. That method should be part of the public interface of each of its collaborators. To the caller&amp;rsquo;s eyes, each of its collaborators belong in the same duck type.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;writing-code-that-leverages-duck-types&#34;&gt;Writing code that leverages duck types&lt;/h4&gt;
&lt;ol start=&#34;10&#34;&gt;
&lt;li&gt;Whenever you see conditional logic that sends a different message depending on the concrete class of a given object, that&amp;rsquo;s the code telling you that it needs a duck type or interface.&lt;/li&gt;
&lt;li&gt;Come up with a message that makes sense from the perspective of the caller and add it to each of the classes expected by your code in the conditional. These classes now share the same public interface, they are of the same duck type. Then remove the conditional and just call that method. Replace conditional logic with &lt;a href=&#34;https://en.wikipedia.org/wiki/Polymorphism_(computer_science)&#34;&gt;polymorphism&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In general, try to avoid code that explicitly mentions concrete classes or checks for the existence of particular methods in order to determine further behavior. Instead, come up with a shared interface and send those messages to the collaborators regardless of their actual type.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Higly conditional and concrete logic like this&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Trip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; IEnumerable&amp;lt;Bicycle&amp;gt; Bicycles { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; IEnumerable&amp;lt;Customer&amp;gt; Customers { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; Vehicle Vehicle { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; Prepare(IEnumerable preparers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; preparer &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;in&lt;/span&gt; preparers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (preparer &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;is&lt;/span&gt; Mechanic)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ((Mechanic)preparer).PrepareBicycles(Bicycles);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (preparer &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;is&lt;/span&gt; TripCoordinator)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ((TripCoordinator)preparer).BuyFood(Customers);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (preparer &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;is&lt;/span&gt; Driver)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ((Driver)preparer).GasUp(Vehicle);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                ((Driver)preparer).FillWaterTank(Vehicle);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Mechanic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareBicycles(IEnumerable&amp;lt;Bicycle&amp;gt; bicycles) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;TripCoordinator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; BuyFood(IEnumerable&amp;lt;Customer&amp;gt; customers) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Driver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; FillWaterTank(Vehicle vehicle) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; GasUp(Vehicle vehicle) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;hellip;can be rewritten to be more abstract if we leverage polymorphism. Like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Trip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; IEnumerable&amp;lt;Bicycle&amp;gt; Bicycles { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; IEnumerable&amp;lt;Customer&amp;gt; Customers { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; Vehicle Vehicle { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// This method can be much simpler now, and abstract.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// Ready to collaborate with any &amp;#34;TripPreparer&amp;#34;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// The conditional logic has been replaced with polymorphism.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; Prepare(IEnumerable&amp;lt;ITripPreparer&amp;gt; preparers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;foreach&lt;/span&gt; (&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; preparer &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;in&lt;/span&gt; preparers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            preparer.PrepareTrip(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// New interface that all preparers implement. It has a single method.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// It greatly simplifies the communication between Trip and its many&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// possible preparers.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ITripPreparer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareTrip(Trip trip);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Mechanic&lt;/span&gt; : ITripPreparer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareTrip(Trip trip)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PrepareBicycles(trip.Bicycles);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareBicycles(IEnumerable&amp;lt;Bicycle&amp;gt; bicycles) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;TripCoordinator&lt;/span&gt; : ITripPreparer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareTrip(Trip trip)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        BuyFood(trip.Customers);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; BuyFood(IEnumerable&amp;lt;Customer&amp;gt; customers) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Driver&lt;/span&gt; : ITripPreparer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; PrepareTrip(Trip trip)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FillWaterTank(trip.Vehicle);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        GasUp(trip.Vehicle);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; FillWaterTank(Vehicle vehicle) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; GasUp(Vehicle vehicle) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;ol start=&#34;13&#34;&gt;
&lt;li&gt;The one exception to this rule is when dealing with exceptionally stable classes. Like those in your language libraries, where the introduction of duck types would mean modifying core language libraries. Explicit type checks against these classes are usually low cost.&lt;/li&gt;
&lt;li&gt;Duck types are abstract and less obvious in the code. That&amp;rsquo;s why they need to be well documented and tested.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;chapter-6-acquiring-behavior-through-inheritance&#34;&gt;Chapter 6: Acquiring Behavior through Inheritance&lt;/h3&gt;
&lt;h4 id=&#34;about-inheritance&#34;&gt;About inheritance&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Inheritance&lt;/strong&gt; establishes a relationship between two classes where it is said that a subclass B &amp;ldquo;is a&amp;rdquo; superclass A. Subclass and superclass are also referred to as derived class and base class, respectively.&lt;/li&gt;
&lt;li&gt;Inheritance can be more technically defined as an &amp;ldquo;automatic message forwarding mechanism&amp;rdquo;. That is, when a subclass receives a message that it cannot respond to directly (i.e. a method that it does not implement), the language runtime takes care of automatically sending the message to the superclass.&lt;/li&gt;
&lt;li&gt;That is, inheritance establishes a hierarchy where superclasses share their code with their subclasses.&lt;/li&gt;
&lt;li&gt;Subclasses are meant to be specialized versions of their superclass. Subclasses should be &amp;ldquo;the same, plus more&amp;rdquo; when compared to their superclass. They should offer the same public interface.&lt;/li&gt;
&lt;li&gt;Inheritance is ideal to solve the problem where you need a series of slightly different classes that share a lot of behavior.&lt;/li&gt;
&lt;li&gt;A telltale sign that inheritance needs to be applied is when code contains an &amp;ldquo;if&amp;rdquo; statement checking an attribute that contains the &amp;ldquo;category&amp;rdquo; of the object, and based on that determines what code to execute. Watch out for this anti-pattern and for variables with names like &amp;ldquo;type&amp;rdquo;, &amp;ldquo;category&amp;rdquo;, &amp;ldquo;style&amp;rdquo; that control branches in behavior.&lt;/li&gt;
&lt;li&gt;This is an anti-pattern that reveals that the object knows too much and needs to be broken down into smaller pieces. It increases the costs of change.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&amp;rsquo;s what the anti-pattern looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Bicycle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Style { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; TapeColor { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; FrontShock { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; Bicycle(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Style = options[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;style&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        TapeColor  = options[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;tape_color&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FrontShock = options[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;front_shock&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// Checking &amp;#39;style&amp;#39; starts down a slippery slope.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; GetSpares()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (Style == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;road&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;                [&amp;#34;chain&amp;#34;]&lt;/span&gt; = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;11-speed&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;                [&amp;#34;tire_size&amp;#34;]&lt;/span&gt; = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;23&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;                [&amp;#34;tape_color&amp;#34;]&lt;/span&gt; = TapeColor
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (Style == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;mountain&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;                [&amp;#34;chain&amp;#34;]&lt;/span&gt; = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;11-speed&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;                [&amp;#34;tire_size&amp;#34;]&lt;/span&gt; = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;2.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;                [&amp;#34;front_shock&amp;#34;]&lt;/span&gt; = FrontShock
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;h4 id=&#34;applying-inheritance&#34;&gt;Applying inheritance&lt;/h4&gt;
&lt;ol start=&#34;8&#34;&gt;
&lt;li&gt;Be on the lookout for existing classes that may lead you down the wrong path when it comes to inheritance. More often than not, classes that already exist in the code base are not good candidates for extension via inheritance. They are not good candidates to be superclasses.&lt;/li&gt;
&lt;li&gt;The path forward is likely to be a new class to serve as the base, and then update your existing class to be a subclass. Then add other subclasses as peers of it.&lt;/li&gt;
&lt;li&gt;For inheritance to work, the objects being modeled need to truly share a generalization-specialization relationship.&lt;/li&gt;
&lt;li&gt;The superclass needs to define the common behavior that is shared among subclasses. The subclasses define the specializations.&lt;/li&gt;
&lt;li&gt;In many cases, the superclass should be &lt;strong&gt;abstract&lt;/strong&gt;, meaning that they are not supposed to be instantiated. They represent an incomplete object which only becomes whole when looked at in the context of each of its subclasses.&lt;/li&gt;
&lt;li&gt;It almost never makes sense to create a superclass with only a single subclass. In fact, creating an inheritance hierarchy with two subclasses is often risky. You risk coming up with the wrong abstraction.&lt;/li&gt;
&lt;li&gt;Three subclasses is the sweet spot to commit to inheritance. Put off the decision to implement inheritance until that point, if you can. That&amp;rsquo;s the point when there&amp;rsquo;s enough information available to confidently determine an abstraction that will be useful and cost effective.&lt;/li&gt;
&lt;li&gt;If you put off implementing an inheritance hierarchy, then you won&amp;rsquo;t be able to share code between the highly related classes. That will likely lead to code repetition, which is also costly. Consider what costs more: having the repetition for the time being; or doing nothing and waiting for more information to avoid making the wrong decision.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Every decision you make includes two costs: one to implement it and another to change it when you discover that you were wrong&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;When refactoring towards an inheritance hierarchy, consider that &amp;ldquo;promoting&amp;rdquo; code from the concrete subclass up into the abstract superclass is often easier and less error prone.&lt;/li&gt;
&lt;li&gt;Errors in promoting are easy to identify and fix. All that can happen if you miss a promotion is that a subclass that was meant to inherit some behavior won&amp;rsquo;t have it.&lt;/li&gt;
&lt;li&gt;Going in the opposite direction and missing a &amp;ldquo;demotion&amp;rdquo; will produce design errors that are harder to spot and have dire consequences if left alone.&lt;/li&gt;
&lt;li&gt;That would mean that concrete behavior, which does not apply to all subclasses, stays incorrectly in the abstract base class. That&amp;rsquo;ll throw a wrench in the works and the whole inheritance hierarchy will be on shaky grounds. The abstract base class won&amp;rsquo;t be generic enough and subclasses will be tempted to circumvent it.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The general rule for refactoring into a new inheritance hierarchy is to arrange code so that you can promote abstractions rather than demote concretions&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Template_method_pattern&#34;&gt;template method pattern&lt;/a&gt; provides a clean way of defining a common basic algorithm in the superclass and allowing subclasses to supply specializations for it. Superclasses can define an algorithm, and call certain methods in key points within it. These are extension points. These methods can then be implemented by subclasses, letting them control part of the overall logic.&lt;/li&gt;
&lt;li&gt;When promoting concrete code to the more abstract superclass, consider using the template method when methods cannot be promoted wholesale, and have to be broken up instead. The parts that can be promoted become the template method; the parts that can&amp;rsquo;t be become the specialization methods that each concrete subclass implements.&lt;/li&gt;
&lt;li&gt;To avoid future bugs, superclasses should provide default implementations for the specialization methods that it expects its subclasses to implement. These can be no-ops or, even better, raise errors. These errors let developers know that extending this inheritance hierarchy requires these methods to be implemented.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/ruby-hook-methods/&#34;&gt;Hook methods&lt;/a&gt; are a slightly lighter iteration of the template method concept that helps alleviate superclass-subclass coupling. Same principle: let the superclass send a message that the subclass implements in order to provide a specialization.&lt;/li&gt;
&lt;li&gt;A hook method need not be a part of a common abstract algorithm, hence the slight distinction from the full fledged template method design pattern.&lt;/li&gt;
&lt;li&gt;Beware of subclasses explicitly invoking functionality on their superclasses. Languages often offer keywords such as &amp;ldquo;&lt;a href=&#34;https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/base&#34;&gt;base&lt;/a&gt;&amp;rdquo; or &amp;ldquo;&lt;a href=&#34;https://www.rubyguides.com/2018/09/ruby-super-keyword/&#34;&gt;super&lt;/a&gt;&amp;rdquo; that allow easily sending messages to superclasses. These are dangerous because they couple subclasses with their superclasses. They reveal that subclasses know the general algorithm.&lt;/li&gt;
&lt;li&gt;The template method pattern and hook methods invert this dependency, allowing the superclass to call the subclass. Allowing the subclass to provide specializations without knowing too much about the superclass.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&amp;rsquo;s an example of a properly factored inheritance hierarchy:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// The main purpose of the base class is to establish a basic functionality&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// that can be easily extended by subclasses.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// This class cannot be instantiated, as given by the &amp;#34;abstract&amp;#34; modifier.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// This means that our application has no need of holding onto pure Bicycle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// instances, only the concrete subclasses are to be used.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// This abstract class is just a vehicle for sharing code between other classes.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;abstract&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Bicycle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Size { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Chain { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; TireSize { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// Notice how this constructor implements the template method pattern&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// in order to allow subclasses to make changes to the overall algorithm.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// Specifically, it allows them to provide default values for the Chain and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// TireSize attributes as well as run any additional logic after&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// initialization.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; Bicycle(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Size = options.GetValueOrDefault(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;size&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Chain  = options.GetValueOrDefault(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;chain&amp;#34;&lt;/span&gt;) ?? GetDefaultChain();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        TireSize = options.GetValueOrDefault(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;tire_size&amp;#34;&lt;/span&gt;) ?? GetDefaultTireSize();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        AfterInitialize(options);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// This method establishes the basic spares information and allows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// subclasses to supply more by calling the GetLocalSpares hook method.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; GetSpares()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;var&lt;/span&gt; defaultSpares = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;            [&amp;#34;tire_size&amp;#34;]&lt;/span&gt; = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;23&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;            [&amp;#34;chain&amp;#34;]&lt;/span&gt; = &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;11-speed&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;(defaultSpares.Concat(GetLocalSpares()));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// This method, which is marked as abstract, has to be implemented by&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// subclasses. It allows subclasses to contribute specializations.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;abstract&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; GetDefaultTireSize();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// These methods, marked as virtual, all have default implementations of&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// varying complexity but the important aspect is that they can be&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// overridden by subclasses. They also allow subclasses to contribute&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;// specializations.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;virtual&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; AfterInitialize(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;virtual&lt;/span&gt; Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; GetLocalSpares() =&amp;gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;virtual&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; GetDefaultChain() =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;11-speed&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// Notice how the following concrete subclasses are very simple.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// Extending this kind of code is easy, because creating new subclasses is easy.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// They leverage their abstract base class to implement most of their features.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// Their job is to supply specializations on the core logic defined in the base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// class. To do so, they override the hook methods defined by the base class.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;RoadBike&lt;/span&gt; : Bicycle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; TapeColor { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; RoadBike(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options) : &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;base&lt;/span&gt;(options) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; AfterInitialize(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options) =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        TapeColor = options.GetValueOrDefault(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;tape_color&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; GetLocalSpares() =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;() { [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;tape_color&amp;#34;&lt;/span&gt;] = TapeColor };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; GetDefaultTireSize() =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;23&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;MountainBike&lt;/span&gt; : Bicycle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; FrontShock { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; RearShock { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; MountainBike(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options) : &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;base&lt;/span&gt;(options) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; AfterInitialize(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        FrontShock = options.GetValueOrDefault(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;front_shock&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        RearShock = options.GetValueOrDefault(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;rear_shock&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; GetLocalSpares() =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;() { [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;front_shock&amp;#34;&lt;/span&gt;] = FrontShock };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; GetDefaultTireSize() =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;2.1&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;RecumbentBike&lt;/span&gt; : Bicycle
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; Flag { &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;get&lt;/span&gt;; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; RecumbentBike(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options) : &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;base&lt;/span&gt;(options) { }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;void&lt;/span&gt; AfterInitialize(Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; options) =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Flag = options.GetValueOrDefault(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; Dictionary&amp;lt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt;&amp;gt; GetLocalSpares() =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt;() { [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;] = Flag };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; GetDefaultChain() =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;10-speed&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;string&lt;/span&gt; GetDefaultTireSize() =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;28&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;chapter-7-sharing-role-behavior-with-modules&#34;&gt;Chapter 7: Sharing Role Behavior with Modules&lt;/h3&gt;
&lt;h4 id=&#34;about-roles&#34;&gt;About roles&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Using classical inheritance is always optional. Every situation that calls for inheritance could be solved using another technique that allows for sharing code between otherwise unrelated classes.&lt;/li&gt;
&lt;li&gt;The concept of &amp;ldquo;&lt;strong&gt;roles&lt;/strong&gt;&amp;rdquo; is an alternative to classical inheritance. This concept emerges from the need of multiple classes to be used in a particular context to do the same thing. So they themselves need to share behavior.&lt;/li&gt;
&lt;li&gt;Think of a role as an augmented form of a duck type. A group of classes are said to play the same role when they belong in the same duck type or implement the same interface. In addition to exposing the same public interface, roles allow them to share internal behavior.&lt;/li&gt;
&lt;li&gt;Roles are ideal for storing responsibilities that are orthogonal to classes. It allows classes that are otherwise unrelated to share behavior. They establish a &amp;ldquo;behaves like&amp;rdquo; type of relationship between objects, as opposed to the &amp;ldquo;is a&amp;rdquo; relationship that is established with inheritance.&lt;/li&gt;
&lt;li&gt;When you include a module into an existing class, all the methods defined in the module become available to the class. This is the same thing that happens when a subclass inherits from a superclass.&lt;/li&gt;
&lt;li&gt;Many languages offer native features to allow for this kind of relationship between objects. In Ruby, we use &lt;a href=&#34;http://ruby-for-beginners.rubymonstas.org/advanced/modules.html&#34;&gt;Modules&lt;/a&gt;. Other languages use &lt;a href=&#34;https://www.pythontutorial.net/python-oop/python-mixin/&#34;&gt;Mixins&lt;/a&gt;, &lt;a href=&#34;https://www.php.net/manual/en/language.oop5.traits.php&#34;&gt;Traits&lt;/a&gt;, &lt;a href=&#34;https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html&#34;&gt;Default Methods&lt;/a&gt;. Simply put, all these are ways of bundling together a group of methods that can be easily plugged into existing classes.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;writing-inheritable-code&#34;&gt;Writing inheritable code&lt;/h4&gt;
&lt;ol start=&#34;7&#34;&gt;
&lt;li&gt;The same principles, techniques, and anti patterns that apply to the design of duck types and inheritance hierarchies also apply to roles.&lt;/li&gt;
&lt;li&gt;Beware of objects that use a variable with a name like &amp;ldquo;type&amp;rdquo;, &amp;ldquo;category&amp;rdquo; or &amp;ldquo;kind&amp;rdquo; to determine what code to execute. The object is likely concealing (and acting like) two or more types. These would be subclasses or module includers.&lt;/li&gt;
&lt;li&gt;When code is checking the type of an object to decide which message to send it, that&amp;rsquo;s a signal that there&amp;rsquo;s a missing abstraction. There&amp;rsquo;s a duck type or role in there that needs to be explicitly brought to light. A public interface needs to be defined for it. If there is a need to share behavior, put it in a module, mixin, etc.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;All of the code in the abstract superclass should apply to every class that inherits it&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Beware of subclasses or module includers that override a superclass/​module method just to raise a &amp;ldquo;not implemented&amp;rdquo; error. Chances are that if only part of the superclass applies to it, then it doesn&amp;rsquo;t belong in the hierarchy. Or maybe the whole hierarchy needs a redesign.&lt;/li&gt;
&lt;li&gt;Subclasses agree to the contract specified by their superclasses. They must respond to every message in the superclass&amp;rsquo;s public interface, accept the same types of inputs and return the same types outputs.&lt;/li&gt;
&lt;li&gt;Put in other words, &amp;ldquo;subtypes must be substitutable for their supertype&amp;rdquo;. That is, all subclasses should act like their superclass. This means that any code that expects a superclass should be able to work, without change, with all its subclasses as well. That&amp;rsquo;s the Liskov substitution principle.&lt;/li&gt;
&lt;li&gt;Through the concept of &lt;a href=&#34;https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)&#34;&gt;variance&lt;/a&gt;, subclasses have a slightly higher degree of freedom. Subclasses can accept inputs of more abstract types and can return outputs of more concrete types than those specified in the superclass&amp;rsquo;s public interface while still being substitutable for their superclass.&lt;/li&gt;
&lt;li&gt;For example, given a class &amp;ldquo;Object&amp;rdquo; that is a superclass of a class &amp;ldquo;String&amp;rdquo;; if a method in a superclass &amp;ldquo;MyClass&amp;rdquo; accepts a String parameter, a subclass of MyClass could override that same method and accept Object and still be compliant. Likewise, if a method in a superclass returns an Object result, the subclass could return a String for that same method, and still be compliant. Still be substitutable.&lt;/li&gt;
&lt;li&gt;In other words, some code that sends a message with a String parameter can send the same message to a receiver that accepts Object. Likewise, some code that expects an Object as a result of sending a message can send the same message to a receiver that returns a String. Because a String &amp;ldquo;is an&amp;rdquo; Object, any code that works with an Object can work with a String, it&amp;rsquo;ll just treat it like an Object and only access Object&amp;rsquo;s public interface, which String fully supports.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;This is what variance allows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Superclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;virtual&lt;/span&gt; Object DoSomething(String parameter) =&amp;gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; Object();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Subclass&lt;/span&gt; : Superclass
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;override&lt;/span&gt; String DoSomething(Object parameter) =&amp;gt; &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;the result&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Be aware that C# currently does not support variance in parameters, only in return types. So this code would not actually work as it is, since the parameter types are different.&lt;/p&gt;&lt;/blockquote&gt;
&lt;ol start=&#34;17&#34;&gt;
&lt;li&gt;The template method pattern is the ideal technique for creating superclasses that are easy to inherit from. It allows clean separation of an abstract algorithm from the concrete specializations.&lt;/li&gt;
&lt;li&gt;Be on the lookout for code that directly invokes superclass behavior with keywords like &amp;ldquo;super&amp;rdquo; or &amp;ldquo;base&amp;rdquo; etc. Instead, use hook methods to allow subclasses to contribute to parts of the common algorithm.&lt;/li&gt;
&lt;li&gt;Favor shallow hierarchies instead of deep ones. Narrow is also preferable to wide. Wide ones are easier to live with as long as they are shallow. But deep and wide ones are a maintenance nightmare. That is, keep the vertical levels of inheritance as low as you can. Hierarchies with many layers of superclasses are hard to understand and maintain.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2024/02/key-takeaways-from-poodr/hierarchies-come-in-different-shapes.webp&#34; alt=&#34;Four diagrams show hierarchies of boxes. The top left is labeled &amp;ldquo;Shallow, Narrow&amp;rdquo; and has one box on top, with two boxes beneath, each connected to the top one by a line. The bottom left is labeled &amp;ldquo;Deep, Narrow&amp;rdquo; and shows the same diagram, but the box on the bottom left has two boxes of its own beneath it, one of which has its own boxes, et cetera, for a total of five layers, each with two boxes. The top right is labeled &amp;ldquo;Shallow, Wide&amp;rdquo;, and shows one box on top, with a single line connecting to each of five boxes directly beneath it. The bottom right is labeled &amp;ldquo;Deep, Wide&amp;rdquo;, and shows a 5-layer box diagram, with anywhere from 3 to 7 boxes on each level, connected by single lines. Different boxes have their own hierarchy, so boxes on the same level are not always direct siblings.&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;chapter-8-combining-objects-with-composition&#34;&gt;Chapter 8: Combining Objects with Composition&lt;/h3&gt;
&lt;h4 id=&#34;about-composition&#34;&gt;About composition&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Composition&lt;/strong&gt; establishes a &amp;ldquo;has a&amp;rdquo; relationship between objects. It is a technique where you combine simple, independent objects to turn them into larger, more complex ones. Composition combines distinct parts so that the resulting entity is more than the sum of its parts.&lt;/li&gt;
&lt;li&gt;In composition, the container object (or composed object) &amp;ldquo;has a&amp;rdquo; contained component (or part). Mechanically, this usually means that the container&amp;rsquo;s class has an attribute which holds a reference to the part object. It&amp;rsquo;s a dependency that&amp;rsquo;s usually injected via constructor parameter.&lt;/li&gt;
&lt;li&gt;The container communicates with the part via its public interface. The part plays a role, and the container collaborates with it. This means that containers generally interact with their parts through interfaces or duck types.&lt;/li&gt;
&lt;li&gt;Composition is generally a cheaper alternative to code sharing when compared to inheritance.&lt;/li&gt;
&lt;li&gt;When refactoring from inheritance into composition, the parts sometimes need to share some code, in addition to sharing the same public interface. This is because all possible parts play the same role for the container. In these cases, an inheritance hierarchy of parts may be what&amp;rsquo;s needed. Or, they could share behavior via modules or mixins.&lt;/li&gt;
&lt;li&gt;In technical terms, the technique of composition takes two forms: &lt;strong&gt;aggregation&lt;/strong&gt; and, well, &lt;strong&gt;composition&lt;/strong&gt;. Under composition, parts don&amp;rsquo;t have any use or value outside of their container objects. Under aggregation, on the other hand, parts can live on their own.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;factories&#34;&gt;Factories&lt;/h4&gt;
&lt;ol start=&#34;7&#34;&gt;
&lt;li&gt;When creating certain objects becomes complex, encapsulate that complexity into a factory. That way the knowledge is stored in a single place in the code base. In principle, factories are simple: They are objects that create other objects.&lt;/li&gt;
&lt;li&gt;An advantage of factories is that they make the process of turning complex data structures into objects easy. You can have a &amp;ldquo;specification&amp;rdquo;, stored as pure data in a file or database. The factory can then implement the logic that understands the meaning of the data structure and how to create living objects based on it.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;deciding-between-inheritance-and-composition&#34;&gt;Deciding between inheritance and composition&lt;/h4&gt;
&lt;ol start=&#34;9&#34;&gt;
&lt;li&gt;Inheritance and composition are fundamentally code arrangement techniques where logic is distributed among various objects. With inheritance, objects are organized into a strict hierarchical structure and get automatic message delegation. With composition, objects are independent from each other but messages need to be manually delegated.&lt;/li&gt;
&lt;li&gt;In general, &amp;ldquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Composition_over_inheritance&#34;&gt;favor composition over inheritance&lt;/a&gt;&amp;rdquo;. Composition is lower cost (i.e. fewer dependencies) than inheritance in most circumstances where both could be used to solve a problem.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;pros-and-cons-of-inheritance&#34;&gt;Pros and cons of inheritance&lt;/h4&gt;
&lt;ol start=&#34;11&#34;&gt;
&lt;li&gt;When properly applied, inheritance is excellent at producing code that is Reasonable, Usable and Exemplary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inheritable code is Reasonable&lt;/strong&gt; because small changes in code can produce great changes in behavior. This is because code near the top of the hierarchy is defined once but used by all subclasses. Changing such code allows to alter the behavior of many subclasses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inheritable code is Usable&lt;/strong&gt; because superclasses are literally designed to be easy to reuse. Inheritance hierarchies adhere to the &lt;a href=&#34;https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle&#34;&gt;open-closed principle&lt;/a&gt;. It&amp;rsquo;s easy to extend the hierarchy by creating new subclasses without having to touch existing code, thus, reusing it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inheritable code is Exemplary&lt;/strong&gt; because it intrinsically provides a clear path to extend it. Even novice programmers won&amp;rsquo;t have a hard time creating new subclasses when the superclasses implement template methods and hooks which guide any extension efforts.&lt;/li&gt;
&lt;li&gt;One important disadvantage of inheritance is that the cost of mistakes is considerably high. Incorrect applications of inheritance are costly, whether it be that the wrong abstraction was created or that inheritance was just the wrong tool for the job altogether.&lt;/li&gt;
&lt;li&gt;Another disadvantage is that, for other contexts outside of the hierarchy, the ways in which it&amp;rsquo;s possible to interact with the hierarchy are limited. If the behavior defined within the hierarchy needs to be used, a subclass needs to be created. Other use cases may be incapable of tolerating that dependency.&lt;/li&gt;
&lt;li&gt;If you&amp;rsquo;re writing a framework or a library, this aspect becomes even more important. You can&amp;rsquo;t know all the scenarios in which your library will be used, and forcing users to create subclasses in order to reuse the logic defined in the hierarchy may be more than what they can afford.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;pros-and-cons-of-composition&#34;&gt;Pros and cons of composition&lt;/h4&gt;
&lt;ol start=&#34;18&#34;&gt;
&lt;li&gt;&amp;ldquo;When using composition, the natural tendency is to create many small objects that contain straightforward responsibilities that are accessible through clearly defined interfaces&amp;rdquo;. &amp;ldquo;Composition results in applications built of simple, pluggable objects that are easy to extend and have a high tolerance for change&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;When properly applied, composition is excellent at producing code that is Transparent, Reasonable and Usable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Composable code is Transparent&lt;/strong&gt; because small objects are easy to understand and changes have obvious effects. These objects also don&amp;rsquo;t necessarily form part of hierarchies, which means they are not susceptible to changes in superclasses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Composable code is Reasonable&lt;/strong&gt; because its behavior is easy to extend by just implementing new objects that play the role of parts. All new parts need to do is implement the public interface that the container object already expects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Composable code is Usable&lt;/strong&gt; because it&amp;rsquo;s made up of small independent objects. They don&amp;rsquo;t have any structural dependencies preventing them from being reused in different contexts, completely unrelated to the container or even the part role.&lt;/li&gt;
&lt;li&gt;One disadvantage of composition is the fact that it may be more difficult to understand how the whole application works. While the individual objects may be small and simple, how they come together to solve problems may not be.&lt;/li&gt;
&lt;li&gt;Another disadvantage is that objects need to delegate messages to each other manually, as opposed to inheritance where this happens automatically. This means that there is the explicit dependency of the container object having to know which messages to call on its parts.&lt;/li&gt;
&lt;li&gt;Composition excels at separating containers from parts and assembling such objects. However, it doesn&amp;rsquo;t have an answer for the scenario where it is necessary to handle a collection of types of parts that are very similar to each other. That&amp;rsquo;s where inheritance comes in.&lt;/li&gt;
&lt;li&gt;Use inheritance for &amp;ldquo;is a&amp;rdquo; relationships. Use duck types, interfaces, and behavior sharing via modules or mixins for &amp;ldquo;behaves like a&amp;rdquo; relationships. Use composition for &amp;ldquo;has a&amp;rdquo; relationships.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;chapter-9-designing-cost-effective-tests&#34;&gt;Chapter 9: Designing Cost-Effective Tests&lt;/h3&gt;
&lt;h4 id=&#34;the-benefits-of-testing&#34;&gt;The benefits of testing&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;The goal of design is to write code that is easy to change. In order to do that, we need good object-oriented design skills, good refactoring skills and good testing skills.&lt;/li&gt;
&lt;li&gt;Good object-oriented design skills are needed because badly designed code, by definition, is hard to change.&lt;/li&gt;
&lt;li&gt;Good refactoring skills are needed because design needs to be evolving constantly. As new requirements and new information about the domain become available, the code needs to adapt.&lt;/li&gt;
&lt;li&gt;Good testing skills are needed because high value, solid tests enable continuous refactoring without fear of breaking the code.&lt;/li&gt;
&lt;li&gt;Just like design, the true purpose of testing is to reduce costs. Tests do help reduce bugs, provide documentation, and improve the design; but those are only the means through which tests achieve their ultimate goal of reducing the cost of change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests help by finding bugs&lt;/strong&gt;: Test help expose bugs early in the process. Bugs are easier to find and cheaper to correct the closer in time we are to their introduction. Testing at the same time a feature is being implemented catches bugs before they go out the door. Bugs caught early are not given the chance to cause problems or have code depend on them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests help by supplying documentation&lt;/strong&gt;: Tests represent the best and most reliable documentation of the design. When static documents and memories get outdated and/or disappear, tests remain. Write tests that tell the story of how the code works.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests help by deferring design decisions&lt;/strong&gt;: As a code base evolves, there will be spots in the code that are less than stellar. Spots which we&amp;rsquo;re not confident enough in to commit to a particular design. So we postpone making a decision and hack together a solution that works today. However, we know that it will need to be refactored to handle the requirements of tomorrow. These spots represent a lack of knowledge. Knowledge that the design is waiting for in order to improve. While waiting for that knowledge to come, we put the hack behind a clear, stable public interface and write our tests against that. In doing so, we&amp;rsquo;ll be free to refactor into a good design when the missing information arrives. Knowing that the tests have our backs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests help by supporting abstractions&lt;/strong&gt;: &amp;ldquo;Good design naturally progresses toward small independent objects that rely on abstractions&amp;rdquo;. One disadvantage to this is that, while small independent objects are easy to understand by themselves, the behavior of the whole application, with all the little objects working together, becomes obscured. Tests solve that problem by highlighting the abstractions, their interfaces, how to work with them, and how they work together.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests help by exposing design flaws&lt;/strong&gt;: If tests are hard to write, that&amp;rsquo;s the perfect indicator that the code under test is hard to reuse. Which indicates high coupling, which indicates increased costs of change. If testing an object requires a lot of setup and a lot of other objects, then it requires too much context and has too many dependencies.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;what-when-and-how-to-test&#34;&gt;What, when and how to test&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2024/02/key-takeaways-from-poodr/object-under-test-are-like-space-capsules.webp&#34; alt=&#34;A legend at the bottom shows solid blue and green lines labeled &amp;ldquo;depended upon by others&amp;rdquo;, and dashed green and red lines labeled &amp;ldquo;no dependents&amp;rdquo;. The main image is labeled &amp;ldquo;Origins of messages&amp;rdquo;. The left side is labeled &amp;ldquo;A. Received from others&amp;rdquo;, with three solid blue lines moving to the right, terminating at a conical object at the center. The cone is labeled &amp;ldquo;object under test&amp;rdquo;, and has a dotted gray line halfway up around the perimeter, with three dotted red lines branching off, looping around, and pointing back to the grey line. This is labeled &amp;ldquo;B. Sent to self&amp;rdquo;. Extending from the right side of the cone are three green lines, two solid and one dotted. They are labeled &amp;ldquo;C. Sent to others&amp;rdquo;.&#34;&gt;&lt;/p&gt;
&lt;ol start=&#34;11&#34;&gt;
&lt;li&gt;&amp;ldquo;One simple way to get better value from tests is to write fewer of them. The safest way to accomplish this is to test everything just once and in the proper place&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tests should focus only on the incoming messages&lt;/strong&gt; that are defined in each object&amp;rsquo;s public interface (&amp;ldquo;A&amp;rdquo; in the picture above). That is, the public methods. Public interfaces expose the services that a class offers its users. They are also stable, so depending on them is safe. Tests that cover public methods are resilient to refactorings and add value because they exercise objects in the same way that their users in application code do.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Never test private methods&lt;/strong&gt; (&amp;ldquo;B&amp;rdquo; in the picture above). They are meant to be used by the object internally. They change often and other objects should not depend on them because they will have to change with them. The same applies to tests. Tests that exercise private code break on every refactoring.&lt;/li&gt;
&lt;li&gt;An object&amp;rsquo;s test suite should &lt;strong&gt;never assert the return value of outgoing messages&lt;/strong&gt; that it sends to other objects (&amp;ldquo;C&amp;rdquo; in the picture above). These messages are part of the public interface of the receiver object, so the receiver&amp;rsquo;s test suite should be the one testing it.&lt;/li&gt;
&lt;li&gt;On the other hand, an object&amp;rsquo;s test suite should &lt;strong&gt;always assert that necessary outgoing messages are sent&lt;/strong&gt;, and with the correct parameters (&amp;ldquo;C&amp;rdquo; in the picture above).&lt;/li&gt;
&lt;li&gt;A &amp;ldquo;test of state&amp;rdquo; is a test that asserts the return value of a method.&lt;/li&gt;
&lt;li&gt;A &amp;ldquo;test of behavior&amp;rdquo; is a test that asserts whether the object under test calls a particular method on another object, how many times, and with what parameters.&lt;/li&gt;
&lt;li&gt;A &amp;ldquo;query&amp;rdquo; is a method call with no side effects that is only made to get some value back.&lt;/li&gt;
&lt;li&gt;A &amp;ldquo;command&amp;rdquo; is a method call that has side effects that are important to the overall application.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;All public methods should be covered by tests of state&lt;/strong&gt;. A test suite should only cover the public methods of its own object under test.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Queries should not be tested for state or behavior&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Commands should be tested for behavior&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Write tests first when it makes sense to do so. Writing tests before implementing the feature establishes an intention for the design from the beginning. Since tests are reused, they make sure the code to be written will have the bare minimum of reusability.&lt;/li&gt;
&lt;li&gt;Testing first is no silver bullet, though. Even though it helps steer the design in the right direction, by itself it won&amp;rsquo;t produce a well-designed application. Fundamental object-oriented design techniques still need to be applied.&lt;/li&gt;
&lt;li&gt;Well-designed applications are easy to change. Well-designed tests may never have to change. This is because they depend on abstractions and public interfaces, which are stable.&lt;/li&gt;
&lt;li&gt;Two major styles of testing exist: Behavior Driven Development and Test Driven Development.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;BDD takes an outside-in approach, creating objects at the boundary of an application and working its way inward, mocking as necessary to supply as-yet-unwritten objects&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;TDD takes an inside-out approach, usually starting with tests of domain objects and then reusing these newly created domain objects in the tests of adjacent layers of code&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Both styles can be followed to produce valuable tests&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2024/02/key-takeaways-from-poodr/bdd-and-tdd-should-be-viewed-as-on-a-continuum.webp&#34; alt=&#34;A blue spectrum line has two objects on either side. At the left end, labeled &amp;ldquo;More outside in BDD&amp;rdquo;, are three concentric green circles, with the outermost labeled &amp;ldquo;1&amp;rdquo;, the middle labeled &amp;ldquo;2&amp;rdquo;, and the innermost labeled &amp;ldquo;3&amp;rdquo;. Each label is outside of its circle, with an arrow pointing to the corresponding circle. At the right end, labeled &amp;ldquo;More inside out TDD&amp;rdquo;, are three identical concentric green circles, this time with the innermost labeled 1, the middle labeled 2, and the outer labeled 3. Each number label lies in the circle and points outward.&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;writing-valuable-tests&#34;&gt;Writing valuable tests&lt;/h4&gt;
&lt;ol start=&#34;30&#34;&gt;
&lt;li&gt;&lt;strong&gt;Incoming messages (i.e. public methods) need to be covered by tests of state&lt;/strong&gt;. That is, the values that they return must be validated.&lt;/li&gt;
&lt;li&gt;Be on the lookout for public methods that don&amp;rsquo;t receive any calls. These are good candidates for deletion. If no other object calls it, then it needs to be private.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Objects should be tested in isolation&lt;/strong&gt;. When that&amp;rsquo;s not possible, there&amp;rsquo;s a problem with the design. It means that the object is too coupled to its collaborators and can&amp;rsquo;t be reused on its own. It needs to be refactored.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s important that objects are tested in isolation because a test suite should care only about the one object that its testing. The other objects will be tested by their own test suites. Changes in an object should affect its own test suite, not that of other objects.&lt;/li&gt;
&lt;li&gt;When the object under test depends on another object in order to work properly, refactor into dependency injection and have the test provide the dependency that way.&lt;/li&gt;
&lt;li&gt;When using dependency injection, don&amp;rsquo;t pass in a concrete, &amp;ldquo;real&amp;rdquo; object in your tests. Instead, inject a &lt;strong&gt;test double&lt;/strong&gt; or &lt;strong&gt;mock&lt;/strong&gt; into the object under test.&lt;/li&gt;
&lt;li&gt;Dependency injection also hints at the emergence of a role, interface, or duck type. Instead of depending on a concrete class, refactor the object under test to depend on a role. The double or mock in the test suite will be one of the objects that play the collaborator role that the object under test expects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Private methods and query method calls need not be tested at all&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Testing private methods is redundant because they are internal to the object under test and invoked by public methods, which already have tests.&lt;/li&gt;
&lt;li&gt;Private methods are also unstable. Not meant to be depended on because they change often. That will make for brittle tests.&lt;/li&gt;
&lt;li&gt;Private methods covered by tests may mislead others in thinking that the method is stable and, thus, dependable.&lt;/li&gt;
&lt;li&gt;Query method call results are not relevant to the overall application, only to the object under test. They are hidden within it. Also, the receiver of the query already includes tests for it, given that it is part of its public interface. So, they should be ignored by the test suite.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Command method calls do need to be covered by tests&lt;/strong&gt; in order to prove that they were called with the correct parameters. In other words, it is the responsibility of the object under test to send that message, so its test suite needs to prove it.&lt;/li&gt;
&lt;li&gt;Mocks are the way to test that command messages get sent. They help with tests of behavior. Using mocks injected into the object under test, a test case can validate that the method is called properly.&lt;/li&gt;
&lt;li&gt;Commands should be tested for behavior, not state. So, mocks should not be used for tests of state. That is, tests should not be concerned with asserting what they return. However, they can be configured to return some value, if the operation requires it.&lt;/li&gt;
&lt;li&gt;In dynamically typed languages that don&amp;rsquo;t have a compiler to do type checks, it is important to test objects for conformance with the public interfaces of their roles, and for proper integration with their inheritance hierarchies.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;&lt;strong&gt;Tests should document the existence of roles, prove that each of their players behave correctly, and show that dependents interact with them appropriately&lt;/strong&gt;&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Pragmatically, this means writing test cases that assert whether objects implement the specific messages defined in their roles&amp;rsquo; public interface and those that their superclasses expect from them.&lt;/li&gt;
&lt;li&gt;Multiple subclasses will undoubtedly share many of the same tests. In those cases, try to encapsulate the test cases into reusable components that every subclass&amp;rsquo;s test suite can invoke. Just like in application code, it&amp;rsquo;s better to avoid repetition.&lt;/li&gt;
&lt;li&gt;Testing abstract base classes can sometimes be challenging because they are not supposed to be instantiated. In some languages, it is downright impossible to instantiate classes marked as abstract. For these scenarios, a test-specific subclass can be created with minimal implementation that allows tests to exercise the base class.&lt;/li&gt;
&lt;li&gt;To avoid test brittleness, test doubles that play certain roles and inherit from superclasses should also be tested for conformance.&lt;/li&gt;
&lt;/ol&gt;

      </content>
    </entry>
  
    <entry>
      <title>Comparison of Lightweight CSS Frameworks</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2022/01/comparison-of-lightweight-css-frameworks/"/>
      <id>https://www.endpointdev.com/blog/2022/01/comparison-of-lightweight-css-frameworks/</id>
      <published>2022-01-13T00:00:00+00:00</published>
      <author>
        <name>Seth Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2022/01/comparison-of-lightweight-css-frameworks/house-frame.jpg&#34; alt=&#34;The frame of a house in front of a mountain range&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen --&gt;
&lt;p&gt;Several months ago I was building a new website and needed a CSS framework. There are many new CSS frameworks around now, so I decided to do several small trial runs and compare them to find the most fitting for our site.&lt;/p&gt;
&lt;p&gt;Initially I tried using Foundation, which this site is built on, but I ran into a problem: Foundation and other popular frameworks are powerful, but they have more features than I needed, and they take up too much disk space for a modest website. Foundation is about 6000 lines long and 200kB unminified. It can be shrunk by removing components you don&amp;rsquo;t need, but the time it takes to slim a large CSS framework down to your needs can be more than it&amp;rsquo;s worth, especially if you want to change any styling.&lt;/p&gt;
&lt;p&gt;Instead of adapting a larger framework to my needs, I looked into lightweight CSS frameworks. These aim to provide boilerplate components, better styling for buttons, forms, tables, and the like, all at the cost of very little disk space.&lt;/p&gt;
&lt;p&gt;I like to modify the source CSS as needed, so all of the sizes I list will be unzipped and unminified. They are also from my brief real-world testing on one machine, so your mileage may vary.&lt;/p&gt;
&lt;h3 id=&#34;bulma&#34;&gt;Bulma&lt;/h3&gt;
&lt;p&gt;Bulma looked very attractive at first. It has sleek, modern design and is quite popular, with a good-sized community for support. But for our site, it was still too big. I only used a few components and layout helpers, a fraction of its 260kB — around 50kB bigger than Foundation, in my tests!&lt;/p&gt;
&lt;h3 id=&#34;minicss&#34;&gt;mini.css&lt;/h3&gt;
&lt;p&gt;mini.css had some great things going for it, but got pushed out by even smaller options which I&amp;rsquo;ll cover shortly. It took up about 46kB with all the bells and whistles.&lt;/p&gt;
&lt;p&gt;The use of flex is a bonus, but it&amp;rsquo;s a little too style agnostic for the website I was working on; I would have overridden a lot of its styling, making the overhead size even larger.&lt;/p&gt;
&lt;p&gt;It has options for using SCSS or CSS variables, which I always like to see. I prefer SCSS&amp;rsquo;s added features and variables, but if you would rather use vanilla CSS, mini.css has a plain option using CSS variables, which I don&amp;rsquo;t see too often.&lt;/p&gt;
&lt;h3 id=&#34;purecss&#34;&gt;Pure.css&lt;/h3&gt;
&lt;p&gt;Pure.css offers similar features to the other frameworks on this list, and weighing in at around 17kB, it competes well in size. However, I wasn&amp;rsquo;t a big fan of its look, and with some odd omissions, notably, the absence of a &lt;code&gt;container&lt;/code&gt; class for horizontally centering content, it was edged out by the competition.&lt;/p&gt;
&lt;h3 id=&#34;skeleton&#34;&gt;Skeleton&lt;/h3&gt;
&lt;p&gt;Skeleton has very clean styling and a good selection of minimal components. It&amp;rsquo;s tiny, weighing in at 12kB. Unfortunately, it hasn&amp;rsquo;t had a release since 2014, and uses &lt;code&gt;float&lt;/code&gt; instead of Flexbox, which took it out of the running for building a more modern site.&lt;/p&gt;
&lt;h3 id=&#34;milligram&#34;&gt;Milligram&lt;/h3&gt;
&lt;p&gt;Milligram feels like a spiritual successor to Skeleton: It covers a similar scope, and has a simple, clean design reminiscent of Skeleton&amp;rsquo;s. In lieu of using classes, it usually applies styling directly to HTML tags. This is a choice I like, since I don&amp;rsquo;t follow the Tailwind CSS approach of creating websites purely in HTML, with agnostic classes applied to the layout.&lt;/p&gt;
&lt;p&gt;It also has an SCSS offering, so it&amp;rsquo;s easy to drop components you don&amp;rsquo;t want, making it even tinier!&lt;/p&gt;
&lt;p&gt;The size and simplicity of Milligram made it win the bid. It has worked quite well, providing just enough framework to be useful for small websites, but getting out of the way so that you can do your own styling.&lt;/p&gt;
&lt;h3 id=&#34;making-the-most-of-your-lightweight-framework&#34;&gt;Making the most of your lightweight framework&lt;/h3&gt;
&lt;p&gt;Hopefully this post will give you an idea of what each of these frameworks is like, but the best way to test them is by trying them yourself! These five were fairly quick to spin up and test out on the website I was working on, and doing the same will give you the best idea of what your website needs.&lt;/p&gt;
&lt;p&gt;With frameworks that are only a few kilobytes, you can also read through the entire source. I tried to look through enough of each framework&amp;rsquo;s CSS files to become familiar with its way of doing things. This eased the whole website-building process, and will help you find a framework that matches your style of web development.&lt;/p&gt;
&lt;p&gt;Also see my colleague Afif&amp;rsquo;s article &lt;a href=&#34;/blog/2021/12/responsive-website-with-tailwindcss/&#34;&gt;Building responsive websites with Tailwind CSS&lt;/a&gt; for an in-depth look at Tailwind CSS.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Building responsive websites with Tailwind CSS</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2021/12/responsive-website-with-tailwindcss/"/>
      <id>https://www.endpointdev.com/blog/2021/12/responsive-website-with-tailwindcss/</id>
      <published>2021-12-03T00:00:00+00:00</published>
      <author>
        <name>Afif Sohaili</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2021/12/responsive-website-with-tailwindcss/banner.jpg&#34; alt=&#34;Sunset over lake and mountains&#34;&gt;&lt;/p&gt;
&lt;!-- photo by Seth Jensen --&gt;
&lt;p&gt;&lt;a href=&#34;https://tailwindcss.com/&#34;&gt;Tailwind CSS&lt;/a&gt; is a CSS framework, like Bootstrap, Bulma, and Foundation. However, Tailwind does things in a less conventional way when compared to traditional CSS frameworks. Instead of providing CSS classes based on components or functional roles (e.g. &lt;code&gt;.card&lt;/code&gt; or &lt;code&gt;.row&lt;/code&gt;), Tailwind only provides utility classes, in which each class does only one specific thing a CSS attribute usually does, such as &lt;code&gt;m-4&lt;/code&gt; for &lt;code&gt;margin: 1rem&lt;/code&gt; or &lt;code&gt;mt-8&lt;/code&gt; for &lt;code&gt;margin-top: 2rem&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Bootstrap, one can simply apply the provided &lt;code&gt;.card&lt;/code&gt; CSS class to have a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; styled like a card the Bootstrap way. In Tailwind, the styles have to be constructed with a string of different atomic classes. E.g. the equivalent of a Bootstrap&amp;rsquo;s &lt;code&gt;.card&lt;/code&gt; would be something like &lt;code&gt;relative flex flex-col break-words bg-white bg-clip-border min-w-0 rounded border&lt;/code&gt;. Verbose, yes, but this gives flexibility for the developers to define the appearance of a &lt;code&gt;.card&lt;/code&gt; element themselves (e.g. there could be multiple variants of appearances of a &lt;code&gt;.card&lt;/code&gt;) without having to worry about overriding inherited/​cascading CSS classes, which are typically the cause of many CSS bugs in production.&lt;/p&gt;
&lt;h3 id=&#34;atomic-css&#34;&gt;Atomic CSS&lt;/h3&gt;
&lt;p&gt;The first thing most notice when developing with Tailwind is how wordy CSS class lists can get. It feels almost like using the &lt;code&gt;style=&amp;quot;&amp;quot;&lt;/code&gt; attribute to write CSS. In the traditional approach to CSS, suppose there are two elements with identical margins:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;card&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;block&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;container&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;rem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, we can see that margin is declared twice. Those duplicates are going to be a few extra bytes in the final CSS payload.&lt;/p&gt;
&lt;p&gt;With Tailwind, however, this is how the equivalent would be written:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;block m-4&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;m-4&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, both of the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s are reusing the same class &lt;code&gt;m-4&lt;/code&gt;, which is provided out-of-the-box by Tailwind. This approach ensures that the project&amp;rsquo;s CSS does not grow, which is important for good user experience. Constructing the CSS of a page is a render-blocking task in a web page load. So, the bigger the CSS, the longer the wait time for a user to see something on the browser. Yes, the HTML payload will grow, but just by a little.&lt;/p&gt;
&lt;p&gt;One of the differences between using Tailwind CSS classes and using &lt;code&gt;style&lt;/code&gt; attribute is that the latter cannot be used to style pseudoclasses (e.g. &lt;code&gt;:hover&lt;/code&gt;, &lt;code&gt;:disabled&lt;/code&gt;). With CSS classes, that is achievable, but there are special prefixes that Tailwind provides for each of the variants to take effect.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!-- margin: 1rem by default, margin: 2rem on hover --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;m-4 hover:m-8&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!-- white background by default, light gray background when disabled --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;bg-white disabled:bg-gray-100&amp;#34;&lt;/span&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Keep in mind that not all variants/​pseudoclasses are supported by default, as this would make the development output of a Tailwind CSS file really big to cater all of the possible variants. To have them supported, it has to be configured inside the project&amp;rsquo;s &lt;code&gt;tailwind.config.js&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// tailwind.config.js
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;module.exports = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  variants: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    extend: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      backgroundColor: [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;active&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;      borderColor: [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;focus-visible&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;first&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;      textColor: [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;visited&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or, if the project is on Tailwind CSS v2.1+, the developers can enable Just-in-Time mode, which grants access to all variants out-of-the-box while also being more functional in development mode.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&#34;https://tailwindcss.com/docs/just-in-time-mode&#34;&gt;Just-in-Time mode&lt;/a&gt; for more details.&lt;/p&gt;
&lt;h3 id=&#34;shaking-off-the-unused-css&#34;&gt;Shaking off the unused CSS&lt;/h3&gt;
&lt;p&gt;By default, Tailwind will be loading the whole Tailwind CSS project files, with CSS declarations on almost every possible CSS rule. There are a lot in there that a developer might never use. To put that into context, there are 105 different values just for grid and flexbox gaps. Most projects aren&amp;rsquo;t likely to use them all, so Tailwind needs a way to remove the unused CSS when generating the final CSS build for production use.&lt;/p&gt;
&lt;p&gt;This is where PurgeCSS comes in. PurgeCSS is a plugin that analyzes all CSS, HTML, and JavaScript files in the project and removes unused CSS declarations from the final build. This tool is available as a PostCSS, Webpack, Gulp, Grunt, or Gatsby plugin.&lt;/p&gt;
&lt;p&gt;Because PurgeCSS analyzes the project&amp;rsquo;s source code to find exact matches of a given CSS style, a CSS class cannot be used through string concatenations or PurgeCSS will not be able to detect that the given Tailwind class is used.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-react&#34; data-lang=&#34;react&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// SomeComponent.jsx
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;const&lt;/span&gt; SomeComponent = (props) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;className&lt;/span&gt;={&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;text-&amp;#39;&lt;/span&gt; + props.color}&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Some text
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// &amp;lt;SomeComponent color=&amp;#39;gray-400&amp;#39;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// In this case, `text-gray-400` will be removed by PurgeCSS in the final CSS 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;// production build because it does not know that the component is using it.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;drying-it-up&#34;&gt;DRYing it up&lt;/h3&gt;
&lt;p&gt;Suppose we have two cards on the page and we want their appearance to be consistent. In the traditional CSS approach, both these two cards will just have the &lt;code&gt;.card&lt;/code&gt; CSS class, and the same styles would be applied to both of them. In Tailwind we can&amp;rsquo;t do that, however, and it doesn&amp;rsquo;t make sense to be repeating 7 or 8 or more different class names on both HTML elements on the page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-react&#34; data-lang=&#34;react&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;const&lt;/span&gt; AppButton = () =&amp;gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;className&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;py-2 px-4 font-semibold rounded-lg shadow-md&amp;#39;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    I&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&amp;#39;&lt;/span&gt;m a button
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// Just use &amp;lt;AppButton&amp;gt; everywhere and their appearances will be consistent
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;// No need to repeat the CSS classes for all three components
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;render(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Form&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;AppButton&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;AppButton&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;AppButton&lt;/span&gt;/&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Form&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Therefore, Tailwind can be easier to implement in component-based frameworks, such as Vue or React. But even if you&amp;rsquo;re not using any of them and are just building a plain HTML file, Tailwind provides a way to compose these classes together by using &lt;code&gt;@apply&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;@apply&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;py-2&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;px-4&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;font-semibold&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;rounded-lg&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;shadow-md&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt;.&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;success&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;@apply&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;py-2&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;px-4&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;font-semibold&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;rounded-lg&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;shadow-md&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;text-white&lt;/span&gt; &lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;bg-green-400&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, &lt;code&gt;.button&lt;/code&gt; and &lt;code&gt;.button.success&lt;/code&gt; classes will be available to us for reuse as in traditional CSS.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!-- py-2 px-4 font-semibold rounded-lg shadow-md gets applied when using &amp;#34;button&amp;#34; --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;button&amp;#34;&lt;/span&gt;&amp;gt;I&amp;#39;m a button&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!-- py-2 px-4 font-semibold rounded-lg shadow-md text-white bg-green-400 gets applied --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;button success&amp;#34;&lt;/span&gt;&amp;gt;I&amp;#39;m a green button&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;button&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;building-a-responsive-page-using-tailwind&#34;&gt;Building a responsive page using Tailwind&lt;/h3&gt;
&lt;p&gt;Now let&amp;rsquo;s look at responsive design. Suppose we want to implement a page with a navigation bar, a sidebar, a content area, and a footer:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2021/12/responsive-website-with-tailwindcss/responsive-desktop.png&#34; alt=&#34;Layout with Tailwind CSS - desktop view&#34;&gt;&lt;/p&gt;
&lt;p&gt;And the sidebar and content area should collapse into one column on mobile devices, like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2021/12/responsive-website-with-tailwindcss/responsive-mobile.png&#34; alt=&#34;Layout with Tailwind CSS - mobile view&#34;&gt;&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s have the basic page layout:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;nav&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;p-4 bg-gray-100&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ul&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;flex gap-2 justify-end&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;Home&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;About&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;Contact&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;nav&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;flex flex-col&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;aside&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;flex items-center justify-center p-4 bg-red-100&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Sidebar
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;aside&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;main&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;min-h-screen p-4 bg-green-100&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Sit eos nam quam nemo qui. Quas recusandae praesentium ratione incidunt sunt commodi labore Nemo nemo error molestias saepe ducimus? Porro reprehenderit voluptatibus nihil voluptate quia. Voluptatibus autem maiores vero?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Consectetur veniam voluptate esse amet debitis eius? Voluptatem officia quibusdam voluptates cum rerum Odio rem maiores laborum commodi cum. Nobis numquam quia nemo maiores repellendus error fuga Repellendus consequatur laudantium?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Elit vitae sit reprehenderit sit laboriosam Ratione iusto numquam corrupti ullam libero! Nisi veritatis facere repudiandae eos perspiciatis recusandae veritatis. Cupiditate temporibus repellat tempore optio numquam id! Perferendis maxime unde
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Dolor autem dolore tempora atque provident. Maxime quos ipsum porro non suscipit. Consectetur et perspiciatis perspiciatis illum quos Ab nostrum unde facere nemo mollitia, saepe ab? Vitae tempore hic accusamus
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Elit labore odit error pariatur cupiditate Ex sequi accusantium maxime et vero Unde quo laboriosam illo ipsam modi eaque Delectus dolorem quas quidem reprehenderit fugiat! Exercitationem provident voluptatum perferendis ut.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;main&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;p-4 bg-yellow-100&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;h5&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;font-bold&amp;#34;&lt;/span&gt;&amp;gt;Footer links&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;h5&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;Home&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;About&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;Contact&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Tailwind official documentation recommends taking a mobile-first approach. Hence, all classes without any screen-size variants will be applied to all screen sizes. Tailwind then provides several screen-size variants such as &lt;code&gt;sm&lt;/code&gt;, &lt;code&gt;lg&lt;/code&gt;, &lt;code&gt;xl&lt;/code&gt;, and &lt;code&gt;2xl&lt;/code&gt; that can be used to control the appearance on specific screen sizes range.&lt;/p&gt;
&lt;p&gt;This is what we&amp;rsquo;re doing here. As you can see, we&amp;rsquo;re using flexbox layout to collapse all elements down to a single column.&lt;/p&gt;
&lt;h4 id=&#34;responsive-variants&#34;&gt;Responsive variants&lt;/h4&gt;
&lt;p&gt;Now, let&amp;rsquo;s add Tailwind&amp;rsquo;s responsive variants so that the page is responsive to screen sizes. In our case, what we would want is to have &lt;code&gt;aside&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt; placed side-by-side when there&amp;rsquo;s enough real estate on the screen. To achieve that, we would need to switch the &lt;code&gt;flex-col&lt;/code&gt; class to &lt;code&gt;flex-row&lt;/code&gt; on bigger screen sizes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;flex flex-col md:flex-row&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;aside&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;flex items-center justify-center p-4 bg-red-100 md:flex-none md:w-1/3 lg:w-1/4&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!-- sidebar --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;aside&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;main&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;min-h-screen p-4 bg-green-100&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;&amp;lt;!-- main content --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;main&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;flex-col md:flex-row&lt;/code&gt; here does the trick for us. &lt;code&gt;md&lt;/code&gt; variants, by default, kick in when the screen width is at a minimum of 768px. At that point, our flexbox will change from the column layout to the row layout, displaying our &lt;code&gt;aside&lt;/code&gt; and &lt;code&gt;main&lt;/code&gt; elements side-by-side in one row. To better distribute the width, we specify &lt;code&gt;md:w-1/3&lt;/code&gt; and &lt;code&gt;lg:w-1/4&lt;/code&gt; classes to the sidebar. &lt;code&gt;w-1/3&lt;/code&gt; and &lt;code&gt;w-1/4&lt;/code&gt; sets the width of the elements to one-third and one-fourth of the parent container respectively. The &lt;code&gt;md&lt;/code&gt; and &lt;code&gt;lg&lt;/code&gt; variants both control at what screen sizes should Tailwind apply which styles.&lt;/p&gt;
&lt;iframe width=&#34;770&#34; height=&#34;434&#34; src=&#34;https://www.youtube.com/embed/M9Wj5dG_N6w&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;It can be a bit daunting to start, but once you get a handle on it, Tailwind CSS is a great option for rapidly building user interfaces with total control over the styles. Unlike other frameworks, Tailwind does not attempt to provide a default styling of any component, allowing every site that uses Tailwind to be truly unique from another.&lt;/p&gt;
&lt;p&gt;These responsive variants can be applied to any other CSS class from Tailwind, providing a powerful way to build responsive user interfaces. The very thin abstraction over CSS provides developers with a greater flexibility and control over the design while being a good constraint to guide the development process.&lt;/p&gt;
&lt;p&gt;Happy styling!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Converting to Hugo</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2021/08/converting-to-hugo/"/>
      <id>https://www.endpointdev.com/blog/2021/08/converting-to-hugo/</id>
      <published>2021-08-23T00:00:00+00:00</published>
      <author>
        <name>Seth Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2021/08/converting-to-hugo/manhattan-view.jpg&#34; alt=&#34;A view of Manhattan from the Empire State Building&#34;&gt;&lt;/p&gt;
&lt;!-- Photo by Seth Jensen --&gt;
&lt;p&gt;We recently converted the End Point website from &lt;a href=&#34;https://middlemanapp.com/&#34;&gt;Middleman&lt;/a&gt; to &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;. I’ll go into more detail shortly, but the general result has been &lt;em&gt;much&lt;/em&gt; better build times with less configuration and better support for local development.&lt;/p&gt;
&lt;h3 id=&#34;background&#34;&gt;Background&lt;/h3&gt;
&lt;p&gt;In 2017 we converted this website from a Ruby on Rails app to a static site. With tons of high-quality static site generator options, we could implement the shiny features used by our &lt;a href=&#34;/blog/2009/10/new-end-point-site-rails-jquery-flot/&#34;&gt;Rails site in 2009&lt;/a&gt; with less overhead and quicker load times.&lt;/p&gt;
&lt;p&gt;We also wanted to move away from Blogger to self-hosting our blog, &lt;a href=&#34;/blog/2017/11/using-github-for-blog-comments/&#34;&gt;using GitHub issues for comments&lt;/a&gt;. We ended up switching to Middleman, a static site generator written in Ruby, and had a mostly positive experience. Ruby was a good fit switching from Rails, and (if I remember correctly) Middleman had pretty competitive performance.&lt;/p&gt;
&lt;p&gt;With over 1000 blog posts at the time, as well as lots of other pages, our site was quite slow to build—3.5 minutes when building with the full blog.&lt;/p&gt;
&lt;p&gt;Middleman had a nice development server, but due to some server-side rewrites, we couldn&amp;rsquo;t use it. Instead, we got around the build times by writing a simple Ruby script to generate an HTML preview, letting our blog authors see what their post would look like, more or less. This worked okay, but was not 100% accurate and made copy-editing and formatting slower than it needed to be for us &amp;ldquo;Keepers of the Blog&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;We started hiding most of the blog from Middleman while building to save time, but build times were still 40 seconds or more. With our patience for long build times waning, as well as Middleman losing most of its support in the development and user community, we decided to get in the market for a new site generator.&lt;/p&gt;
&lt;h3 id=&#34;shopping-around&#34;&gt;Shopping around&lt;/h3&gt;
&lt;p&gt;Before we (🚨 spoiler alert 🚨) settled on Hugo, we tried using &lt;a href=&#34;https://www.getzola.org/&#34;&gt;Zola&lt;/a&gt;, a site generator written in Rust and boasting tiny build times. Zola is a small project, and would have worked fairly well for us, but it had several downsides.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Initial build times were very promising, but slowed down more than expected after adding our now more than 1500 blog posts. We still ended up with very respectable build times of less than 15 seconds.&lt;/li&gt;
&lt;li&gt;As far as I could tell, Zola would have required an &lt;code&gt;_index.md&lt;/code&gt; file in every section and subsection, to hold section settings or to make it a transparent section, passing its files to the parent section. I didn&amp;rsquo;t like the sound of having a couple hundred extra Markdown files, one for every blog year and month.&lt;/li&gt;
&lt;li&gt;At the time of writing, Zola doesn&amp;rsquo;t support custom taxonomy paths. That means we would have our blog tags at &lt;code&gt;www.endpointdev.com/tags/&lt;/code&gt;, instead of our existing (and preferred) &lt;code&gt;www.endpointdev.com/blog/tags/&lt;/code&gt;. This has been &lt;a href=&#34;https://zola.discourse.group/t/custom-path-for-taxonomy-pages/82&#34;&gt;discussed&lt;/a&gt; on Zola forums, but seems to have stalled. This wasn&amp;rsquo;t a complete dealbreaker, but it was disappointing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;making-the-switch-to-hugo&#34;&gt;Making the switch to Hugo&lt;/h3&gt;
&lt;p&gt;We wanted to see if there was another option which solved our issues with Zola. I decided to try Hugo. It&amp;rsquo;s written in Go and is currently one of the most popular static site generators.&lt;/p&gt;
&lt;p&gt;I partially converted the site and blog, and found that Hugo solved our main concerns with Zola:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Build times were close to twice as fast as Zola.&lt;/li&gt;
&lt;li&gt;You can dump as many subdirectories as you want in each section, and they&amp;rsquo;ll still belong to the section but retain the original directory structure.&lt;/li&gt;
&lt;li&gt;Hugo supports custom taxonomy paths through its &lt;a href=&#34;https://gohugo.io/content-management/urls/&#34;&gt;permalinks&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We were also able to shave off a lot of build time by analyzing our &lt;a href=&#34;https://gohugo.io/troubleshooting/build-performance/&#34;&gt;template metrics&lt;/a&gt;—this is one of my favorite features in Hugo.&lt;/p&gt;
&lt;h4 id=&#34;local-development&#34;&gt;Local development&lt;/h4&gt;
&lt;p&gt;So far, we&amp;rsquo;ve had extremely smooth local development. Hugo (like Zola) comes as a standalone single executable, so it&amp;rsquo;s extremely easy to get started or update. This was a huge improvement over Middleman, which required a heap of Ruby gems and plugins. Now every blog author can easily clone our repo, run the development server, and edit their post directly, with the full site building in anywhere from ~10 seconds all the way down to ~2 seconds, depending on the author&amp;rsquo;s machine.&lt;/p&gt;
&lt;p&gt;For blog authors, we were using a fork of an abandoned Middleman plugin. With Hugo, we&amp;rsquo;re using their taxonomies, which have been fairly easy to set up. We were also able to use Hugo&amp;rsquo;s built-in Chroma highlighter, instead of loading and running highlight.js on every blog page.&lt;/p&gt;
&lt;h4 id=&#34;some-drawbacks&#34;&gt;Some drawbacks&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;July 2025 Update: Hugo has seen a lot of development since this post was written in 2021. I&amp;rsquo;ve added Wayback Machine links so the references are historical, but these examples are out of date now. From my usage in the past few years, the documentation has improved quite a bit.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;We&amp;rsquo;re loving the wonderfully fast build times and easy local development. I like the templating fairly well, and the simple configuration is wonderful. But Hugo does have several issues and missing features I&amp;rsquo;d like to see.&lt;/p&gt;
&lt;p&gt;One place Zola wins over Hugo is the ability to easily print the &lt;a href=&#34;https://www.getzola.org/documentation/templates/overview/&#34;&gt;entire context&lt;/a&gt; in a big JSON object. It&amp;rsquo;s a bit hard to navigate, but in my experience much easier and clearer than Hugo, where I have to either try using &lt;code&gt;printf&lt;/code&gt; to display the context&amp;rsquo;s variables, or search through the documentation. This was one of my favorite ways to quickly debug and learn about the inner workings of Zola, and would be very welcome in Hugo as well, without needing to know &lt;a href=&#34;https://pkg.go.dev/fmt&#34;&gt;Go formatting width&lt;/a&gt; and the full shape of Hugo&amp;rsquo;s context object beforehand.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Joe Mooring, a Hugo developer, mentioned that you can print some things with &lt;a href=&#34;https://gohugo.io/functions/debug/dump/&#34;&gt;&lt;code&gt;debug.Dump&lt;/code&gt;&lt;/a&gt;. I tried passing the context with &lt;code&gt;{{ debug.Dump . }}&lt;/code&gt;, which worked well for seeing what context variables are available/​set.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Documentation is another area where Hugo struggles sometimes. Pages often don&amp;rsquo;t feel interconnected and examples are often lacking. Here are a few examples I encountered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Hugo Pipes page &lt;a href=&#34;https://web.archive.org/web/20210728193528/https://gohugo.io/hugo-pipes/scss-sass/&#34;&gt;SASS/​SCSS&lt;/a&gt; shows how to transform Sass files to CSS, but did not link to the very useful &lt;a href=&#34;https://web.archive.org/web/20210617171030/https://gohugo.io/content-management/page-resources/&#34;&gt;Page Resources&lt;/a&gt; page. It turned out I just needed to link to &lt;code&gt;{{ $style.RelPermalink }}&lt;/code&gt;, but as a new user it wasn&amp;rsquo;t clear that the CSS file was considered a &lt;code&gt;Resource&lt;/code&gt;. Having more links to related pages or more examples could save a lot of headaches for newbies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://web.archive.org/web/20210322083411/https://gohugo.io/templates/lookup-order/#hugo-layouts-lookup-rules&#34;&gt;Lookup Order&lt;/a&gt; says under the &lt;code&gt;Layout&lt;/code&gt; section that it &amp;ldquo;can be set in page front matter,&amp;rdquo; but I had to look under &lt;a href=&#34;https://web.archive.org/web/20210620065133/https://gohugo.io/content-management/front-matter&#34;&gt;Front Matter&lt;/a&gt; to see that &lt;code&gt;layout&lt;/code&gt; is the key name. A small change, and didn&amp;rsquo;t take long to experiment and find out, but especially since YAML is case sensitive, having a link to the actual front matter key would be better.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enabling custom outputs on a per-taxonomy basis does not seem to be possible. We want to generate Atom feeds for our blog tags, but not for our blog authors, both of which are taxonomies. As far as I can tell, we have to enable them both and live with the cruft of unnecessary blog author feeds being generated.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Joe also provided a solution to this problem: cascade the &lt;code&gt;outputs&lt;/code&gt; front matter field down from the taxonomy page (e.g., content/tags/_index.md) or from your site configuration.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/configuration/cascade/&#34;&gt;https://gohugo.io/configuration/cascade/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/content-management/front-matter/#cascade-1&#34;&gt;https://gohugo.io/content-management/front-matter/#cascade-1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I tested this and it works like a charm.&lt;/p&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;onward-and-upward&#34;&gt;Onward and upward!&lt;/h3&gt;
&lt;p&gt;It may look (mostly) the same, but on our end it&amp;rsquo;s never been easier to write blog posts or update the website, thanks to Hugo and all its contributors!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>National Braille Press Releases Redesigned Website</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2019/08/national-braille-press-redesigned-website/"/>
      <id>https://www.endpointdev.com/blog/2019/08/national-braille-press-redesigned-website/</id>
      <published>2019-08-28T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2019/08/national-braille-press-redesigned-website/image-0.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;End Point congratulates National Braille Press on the recent release of their &lt;a href=&#34;https://www.nbp.org/&#34;&gt;redesigned website&lt;/a&gt;, launched earlier this week! National Braille Press (NBP) supports the blind and low-vision community with events, initiatives, resources, children’s programs, and a bookstore. NBP has been working with End Point since 2002 and hosts and maintains their website, which is based on the Interchange open-source ecommerce platform.&lt;/p&gt;
&lt;h3 id=&#34;project-phases&#34;&gt;Project Phases&lt;/h3&gt;
&lt;p&gt;End Point started working with NBP on this redesign project in late 2017. We began with a user experience (UX) review &amp;amp; content strategy project which resulted in design directives for our in-house team. Design and plans were completed in mid-2018 and implementation began then. End Point built a new, more powerful search feature and developed a number of ‘cornerstone’ pages while NBP staff worked tirelessly in-house to convert the rest of the pages on their website to the new designs.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;/blog/2019/08/national-braille-press-redesigned-website/image-1.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;leveraging-nbp-in-house-resources&#34;&gt;Leveraging NBP In-House Resources&lt;/h3&gt;
&lt;p&gt;NBP’s wide reach in their community and long history means their website has hundreds of content pages. This can be costly to convert, and for some non-profits, can make a redesign project cost-prohibitive. End Point engineers Greg Davidson and Marco Pessotto worked alongside NBP staff helping them learn the Bootstrap web development toolkit and the steps they needed to take to integrate each page into the new designs. Using these in-house resources dramatically reduced the overall project cost while allowing the content to be converted carefully by hand with accuracy and care.&lt;/p&gt;
&lt;h3 id=&#34;wcag-20-aa-standard&#34;&gt;WCAG 2.0, AA Standard&lt;/h3&gt;
&lt;p&gt;NBP’s user base is heavily centered in the low-vision community, so compliance with user accessibility standards was a main focus of the redesign effort. End Point worked with NBP to make sure all of the engineers on the project were trained in the Web Content Accessibility Guidelines (WCAG 2.0) AA standards and guidelines. Testing for compliance was done with &lt;a href=&#34;https://chrome.google.com/webstore/detail/axe/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US&#34;&gt;AXE&lt;/a&gt; and &lt;a href=&#34;https://wave.webaim.org/&#34;&gt;WAVE&lt;/a&gt; Chrome accessibility plugins. NBP also completed direct user testing with screen readers and devices.&lt;/p&gt;
&lt;p&gt;Congrats again to NBP on completing this project with us!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Expert Help with Your SaaS System</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/04/expert-help-with-saas/"/>
      <id>https://www.endpointdev.com/blog/2018/04/expert-help-with-saas/</id>
      <published>2018-04-23T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;img src=&#34;/blog/2018/04/expert-help-with-saas/123go.jpg&#34; width=&#34;770&#34; height=&#34;485&#34; alt=&#34;1, 2, 3 … Let’s Go!&#34; /&gt;
&lt;p&gt;Are you thinking about starting a new website and using BigCommerce, Shopify, or WooCommerce? The software-as-a-service offerings on the market today can help you get a great-looking, low-cost ecommerce website up and running quickly, but you may need more help than you first expect.&lt;/p&gt;
&lt;p&gt;In order to get the most out of your site, ecommerce consultants like us at End Point can guide you through setup, customize your site to fit your brand, manage all of your technical requirements, and help drive traffic to your site. This post is an overview of services we offer to clients looking for a SaaS solution.&lt;/p&gt;
&lt;h3 id=&#34;select-the-right-vendor&#34;&gt;Select the Right Vendor&lt;/h3&gt;
&lt;p&gt;Working with an expert consultant can help you make the right choices from the start. Sometimes knowing the level of customization that your project requires can be a real challenge. End Point has experience with everything from out-of-the-box SaaS platforms to large-scale, custom software developments—​we take time to understand your requirements and guide you to the perfect solution for your business.&lt;/p&gt;
&lt;h3 id=&#34;custom-design&#34;&gt;Custom Design&lt;/h3&gt;
&lt;p&gt;Most SaaS offerings include ready-to-use, beautiful design templates, but you’ll often find that they require some tweaking. We can customize your design so that it fits perfectly with the look and feel of your brand, without the time and expense of going through the design process from scratch.&lt;/p&gt;
&lt;h3 id=&#34;user-experience-and-navigation&#34;&gt;User Experience and Navigation&lt;/h3&gt;
&lt;p&gt;Working with an ecommerce consultant that has experience with user behavior, site navigation, and business workflows can help you develop the best way to organize your pages and products. With improved navigation, we can ensure that your users are finding what they’re looking for and getting where they’re going quickly and seamlessly.&lt;/p&gt;
&lt;h3 id=&#34;customizing-your-store&#34;&gt;Customizing Your Store&lt;/h3&gt;
&lt;p&gt;Customizing your store to work with your specific needs, like shipping integrations, 3rd party apps, and APIs can be a challenge. End Point can help you research the solutions already in place, or build custom solutions for your site.&lt;/p&gt;
&lt;h3 id=&#34;email-setup&#34;&gt;Email Setup&lt;/h3&gt;
&lt;p&gt;End Point can help you set up your email on your desktop or in the cloud, and can help you configure and maintain all of your in-house email needs.&lt;/p&gt;
&lt;h3 id=&#34;dns-and-domain-names&#34;&gt;DNS and Domain Names&lt;/h3&gt;
&lt;p&gt;End Point has DevOps experts who can make sure everything with your domain name and DNS changes is handled quickly and correctly during the setup or migration of your site from one provider to another.&lt;/p&gt;
&lt;h3 id=&#34;search-engine-optimization-seo&#34;&gt;Search Engine Optimization (SEO)&lt;/h3&gt;
&lt;p&gt;A solid search engine optimization strategy is critical to the success of your website, and therefore critical to the success of your business. A high Google ranking means more page views—​and more conversions. At End Point, we design and build with SEO in mind from the start to help you get the most value from your online presence.&lt;/p&gt;
&lt;h3 id=&#34;payments-and-merchants&#34;&gt;Payments and Merchants&lt;/h3&gt;
&lt;p&gt;End Point has experience with many major merchant vendors. We can help you find the right merchant, be it PayPal, Stripe, Authorize.net, Braintree, etc. We can make sure that payments are set up, tested, and integrated into your business cash flow. We also have experience with PCI compliance and can help you step through an evaluation or mitigation process and get your system in tip-top shape.&lt;/p&gt;
&lt;h3 id=&#34;project-management&#34;&gt;Project Management&lt;/h3&gt;
&lt;p&gt;Are you trying to wrangle a team of people? Your old vendor and your new one? Do you need help in managing the project? Our project managers are here to help you meet your business goals and get to the finish line on time and within budget.&lt;/p&gt;
&lt;h3 id=&#34;system-migrations&#34;&gt;System Migrations&lt;/h3&gt;
&lt;p&gt;Working with an expert consultant can really help when you are moving from one system to another. We have customizable data export and import scripts and many automated tools to move your content to your new platform and can save you hours of moving products and pages by hand.&lt;/p&gt;
&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;
&lt;p&gt;Working with a consultant agency can really give your SaaS project the professional edge you’ll need to compete in today’s ecommerce market. We offer consulting packages to fit your budget and the depth of services that you need. Talk to us today about how we could help get your project off the ground.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;(&lt;a href=&#34;/blog/authors/jon-allen/&#34;&gt;Jon Allen&lt;/a&gt; co-authored this article.)&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Designing for SEO from the Start</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/03/designing-for-seo-from-the-start/"/>
      <id>https://www.endpointdev.com/blog/2018/03/designing-for-seo-from-the-start/</id>
      <published>2018-03-28T00:00:00+00:00</published>
      <author>
        <name>Jon Allen</name>
      </author>
      <content type="html">
        &lt;p style=&#34;clear: both; text-align: right&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2018/03/designing-for-seo-from-the-start/analytics-2.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Search engine optimization (SEO)&lt;/strong&gt; is critical to the success of your website, and therefore critical to the success of your business. A high Google ranking means more page views—​and more conversions. Google rewards websites that are user-friendly and easy-to-navigate, with fresh content and frequent updates. At End Point, we design with SEO in mind from the beginning of the project to help you get the most value from your online presence.&lt;/p&gt;
&lt;p&gt;These are the five main areas that we focus on to improve your ranking:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Content Strategy&lt;/strong&gt;—​You want to provide your users with quality content. We can provide a content strategy to help ensure that your site stays on target, with clear copy, focused messaging, and consistent branding. We’ll help you put together a site that gets visitors where they want to be—​and you’ll reap the rewards with an increase in traffic to your site.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sitemap, Keywords, and Semantic Markup&lt;/strong&gt;—​We dive into the nuts and bolts of your site to make sure that it can be crawled and indexed easily by Google. We produce a prioritized XML sitemap, relevant, long-tail keywords and metadata, descriptive page headings, titles, and URLs. Your site’s code will utilize HTML5 semantic markup to produce a well-structured, hierarchical document that will be easily read by web crawlers—​and humans, too.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Blogging and Social Media&lt;/strong&gt;—​Keeping your website fresh with new links and content is critical for SEO success. Setting up a blog platform makes it easy to quickly generate new content that can draw more visitors to your site. We can also connect you with social media platforms such as Twitter and Facebook to help carry your messages across the web.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Analytics&lt;/strong&gt;—​Google Analytics allows you to watch in real time how users are finding and interacting with your site. Figure out which pages perform the best, which are underperforming, identify trends in user behavior, and calibrate your site to help users get the most out of their experience.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mobile Support&lt;/strong&gt;—​With just over &lt;a href=&#34;https://www.statista.com/statistics/277125/share-of-website-traffic-coming-from-mobile-devices/&#34; target=&#34;_blank&#34;&gt;half&lt;/a&gt; of all web traffic coming from mobile devices, it’s crucial to have a website that’s responsive on any device. Because of the ubiquity of mobile browsing, Google rewards sites that are mobile friendly. We optimize your site to ensure that pages load quickly and display on any laptop, tablet, or smartphone.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There’s no big secret to a strong SEO strategy. It’s all about having engaging, useful content that’s easy to find and navigate. End Point has the knowledge and resources to help your business grow by building you a site that’s clear and focused, and one that’s up to the latest web standards.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here are a few guides that provide more details about what goes into a strong SEO strategy:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://moz.com/beginners-guide-to-seo&#34; target=&#34;_blank&#34;&gt;Moz Beginner’s Guide to SEO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://support.google.com/webmasters/answer/7451184?hl=en&#34; target=&#34;_blank&#34;&gt;Google SEO Starter Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://schema.org/&#34; target=&#34;_blank&#34;&gt;Schema.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>The End Point Design Process</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/03/end-point-design-process/"/>
      <id>https://www.endpointdev.com/blog/2018/03/end-point-design-process/</id>
      <published>2018-03-14T00:00:00+00:00</published>
      <author>
        <name>Jon Allen</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2018/03/end-point-design-process/design-notebook-pen.jpg&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2018/03/end-point-design-process/design-notebook-pen.jpg&#34; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Designing for the web means more than just creating beautiful websites—​whether it’s a marketing site, an ecommerce platform, or a large-scale web application, thoughtful design means better, more intuitive user experiences. The design process provides a roadmap for developers and a shared set of expectations for the clients of what the final product will be.&lt;/p&gt;
&lt;p&gt;If you’ve contracted End Point for design work, or you’re considering it, this post will show you all the steps as we go from an initial concept to a polished design that’s ready for development. You’ll also learn the basic vocabulary of deliverables and some of the tools involved in the process.&lt;/p&gt;
&lt;h3 id=&#34;phase-i-discovery&#34;&gt;Phase I: Discovery&lt;/h3&gt;
&lt;p&gt;Every new app, website, or product starts with an idea. The initial phase of design work means clarifying that idea—​defining its boundaries and goals. Thorough research and investigation are critical for setting the path to success. We interview our clients’ staff, stakeholders, and users to get a comprehensive picture of the current marketplace, discover any pain points in existing workflows, and learn what we can do to make things better. We also take an in-depth look at existing content and, with the client, decide what should stay, what should go, and what needs to be updated or refreshed.&lt;/p&gt;
&lt;p&gt;At the end of this process, we provide our clients with a new sitemap, interview transcripts, and a detailed strategy document. Depending on the client’s needs, we may also produce user flow diagrams, user personas, taxonomies, and a content migration plan.&lt;/p&gt;
&lt;h3 id=&#34;phase-ii-sketching-and-wireframing&#34;&gt;Phase II: Sketching and Wireframing&lt;/h3&gt;
&lt;p&gt;Once the research materials have been gathered, content has been analyzed, and a design strategy is in place, we make sketches, diagrams, and rough mockups so that everyone involved in the project can start to see the overall form of the final product. At this stage, concerns about font, color, or graphics are mostly off the table—​we’re focused on how the parts of the application fit together to create a great user experience.&lt;/p&gt;
&lt;p&gt;Wireframing at End Point is generally done using Balsamiq, a dedicated wireframing application, or Sketch, a more powerful design program that allows the wireframes to be developed into fully-realized design comps.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2018/03/end-point-design-process/wireframes-2.png&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2018/03/end-point-design-process/wireframes-2.png&#34; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;phase-iii-design-comps&#34;&gt;Phase III: Design Comps&lt;/h3&gt;
&lt;p&gt;Often, the wireframes are all a developer needs to begin building an application. If a project has an existing design vocabulary, there may be no need to go further. But if an all-new application or website is being built, then a designer will articulate all of the elements needed to create a custom look and feel—​color, typography, graphics, and more. Interface design isn’t just decorative—​clear labels, semantic colors, eye-catching CTAs (calls to action), and a well-considered hierarchy of page elements all serve to guide the user through the system efficiently and effectively.&lt;/p&gt;
&lt;p&gt;Design comps are presented as a multi-page PDF that shows the client what primary screens of the application will look like. These are created in Adobe Illustrator or Sketch, which both allow for pixel-perfect designs that correspond exactly to the finished product.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;/blog/2018/03/end-point-design-process/grab_illustrator.png&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2018/03/end-point-design-process/grab_illustrator.png&#34; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h3 id=&#34;phase-iv-handoff&#34;&gt;Phase IV: Handoff&lt;/h3&gt;
&lt;p&gt;Once the client has approved the final designs, they’re ready to move to the next stage of the process, where frontend and backend developers turn the finished designs into fully-functional, working software. As development continues, the designer is on hand to help guide the building of the interface and ensure that the design specifications are maintained.&lt;/p&gt;
&lt;p&gt;Looking for help realizing your next project, big or small? &lt;a href=&#34;/contact/&#34;&gt;Get in touch with us&lt;/a&gt; to obtain a copy of our design portfolio, and to find out what End Point can do to turn your next big idea into a reality.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Series Digital joins End Point!</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/06/series-digital-joins-end-point/"/>
      <id>https://www.endpointdev.com/blog/2017/06/series-digital-joins-end-point/</id>
      <published>2017-06-01T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;End Point has the pleasure to announce some very big news!&lt;/p&gt;
&lt;p&gt;After an amicable wooing period, End Point has purchased the software consulting company &lt;a href=&#34;http://www.seriesdigital.com/&#34;&gt;Series Digital&lt;/a&gt;, a NYC-based firm that designs and builds custom software solutions. Over the past decade, Series Digital has automated business processes, brought new ideas to market, and built large-scale dynamic infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.seriesdigital.com/&#34;&gt;&lt;img align=&#34;right&#34; alt=&#34;Series Digital website snapshot&#34; src=&#34;/blog/2017/06/series-digital-joins-end-point/image-0.png&#34; style=&#34;width: 393px; height: 409px; margin-left: 1em&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Series Digital launched in 2006 in New York City. From the start, Series Digital managed large database installations for financial services clients such as Goldman Sachs, Merrill Lynch, and Citigroup. They also worked with startups including Drop.io, Byte, Mode Analytics, Domino, and Brewster.&lt;/p&gt;
&lt;p&gt;These growth-focused, data-intensive businesses benefited from Series Digital’s expertise in scalable infrastructure, project management, and information security. Today, Series Digital supports clients across many major industry sectors and has focused its development efforts on the Microsoft .NET ecosystem. They have strong design and user experience expertise. Their client list is global.&lt;/p&gt;
&lt;p&gt;The Series Digital team began working at End Point on April 3rd, 2017.&lt;/p&gt;
&lt;p&gt;The CEO of Series Digital is Jonathan Blessing. He joins End Point’s leadership team as  Director of Client Engagements. End Point has had a relationship with Jonathan since 2010, and looks forward with great anticipation to the role he will play expanding End Point’s consulting business.&lt;/p&gt;
&lt;p&gt;To help support End Point’s expansion into .NET solutions, End Point has hired &lt;a href=&#34;/team/dan-briones/&#34;&gt;Dan Briones&lt;/a&gt;, a 25-year veteran of IT infrastructure engineering, to serve as Project and Team Manager for the Series Digital group. Dan started working with End Point at the end of March.&lt;/p&gt;
&lt;p&gt;The End Point leadership team is very excited by the addition of Dan, Jonathan, and the rest of the talented Series Digital team: Jon Allen, Ed Huott, Dylan Wooters, Vasile Laur, Liz Flyntz, Andrew Grosser, William Yeack, and Ian Neilsen.&lt;/p&gt;
&lt;p&gt;End Point’s reputation has been built upon its excellence in e-commerce, managed infrastructure, and database support. We are excited by the addition of Series Digital, which both deepens those abilities, and allows us to offer new services.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;/contact/&#34;&gt;Talk to us&lt;/a&gt; to hear about the new ways we can help you!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Case Study: Responsive Design Return on Investment</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/07/case-study-responsive-design-return-on/"/>
      <id>https://www.endpointdev.com/blog/2016/07/case-study-responsive-design-return-on/</id>
      <published>2016-07-21T00:00:00+00:00</published>
      <author>
        <name>Elizabeth Garrett Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;Responsive design has been a hot topic in the e-commerce world for several years now. End Point has worked on many sites over the last few years to transition clients to a responsive design website model. While many large sized retailers have already transitioned to a responsive design, there are many smaller e-commerce sites that are still on an older design model and I would like to show that the return on investment for those stores is still noteworthy.&lt;/p&gt;
&lt;p&gt;The lead of our Interchange team, Greg Hanson, led a responsive design project and I’d like to summarize that work on our blog. For confidentiality, I am leaving out the client’s name in this case.&lt;/p&gt;
&lt;h3 id=&#34;why-go-responsive&#34;&gt;Why Go Responsive?&lt;/h3&gt;
&lt;p&gt;There are two main reasons every e-commerce website, even a small one, needs to become responsive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your customers&lt;/li&gt;
&lt;li&gt;Google&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The march toward mobile sales at this point is undeniable and unstoppable. As more and more people become comfortable using their phones and tablets to purchase things, the bigger this market share will become. Also, Google has begun de-prioritizing websites that do not cater to mobile users. If you are waiting to go responsive because of budget, you might surprised to learn how dramatically the mobile revenue increased for the customer in this case.&lt;/p&gt;
&lt;h3 id=&#34;goals&#34;&gt;Goals&lt;/h3&gt;
&lt;p&gt;This client is a small e-commerce business with a heavy ‘on’ season and ‘off’ season where the business owners could focus on this project. They wanted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To accommodate the increasing mobile user base; they knew it was there from looking at their Google Analytics.&lt;/li&gt;
&lt;li&gt;To increase revenue from mobile users. They could see that they had a 10% mobile user base, but they were converting only a small percentage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;end-points-strategy&#34;&gt;End Point’s strategy&lt;/h3&gt;
&lt;p&gt;Our strategy with this small client, to minimize impact to the business and cost was to:&lt;/p&gt;
&lt;h4 id=&#34;use-bootstrap&#34;&gt;Use Bootstrap&lt;/h4&gt;
&lt;p&gt;Bootstrap is one of many front end frameworks that allows you to create a design template and roll that out to all the pages within a website without having to re-code each and every page in a website. This dramatically increases the speed and decreases cost.&lt;/p&gt;
&lt;h4 id=&#34;break-up-the-work-into-segments&#34;&gt;Break up the work into segments&lt;/h4&gt;
&lt;p&gt;In this case, we had a three phase approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Phase I, re­design the site using Bootstrap but still at fixed width&lt;/li&gt;
&lt;li&gt;Phase II, site checkout sequence changed to responsive&lt;/li&gt;
&lt;li&gt;Phase III, entire site responsive&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;the-project&#34;&gt;The Project&lt;/h3&gt;
&lt;p&gt;Converting the site to Bootstrap was the biggest chunk of the time and money spent on this project. Since we knew this would be the foundation for the changes to come, we took our time getting it right, keeping the client involved every step of the way. We didn’t want to get in the way of their busy season either, so we completed that project and waited a half a year to begin the next piece.&lt;/p&gt;
&lt;p&gt;The second step was updating checkout sequence to be responsive since this was arguably the hardest part about using the non-responsive site on a mobile device. The client considered this piece top priority. Plus, since it was only a few pages, it allowed us all to better understand the scope of coding the rest of the site and give the client an accurate picture of the budget.&lt;/p&gt;
&lt;p&gt;Last, once we had a responsive checkout sequence, we changed the rest of the internal pages to be responsive and rolled out the entire site as responsive and mobile friendly.&lt;/p&gt;
&lt;h3 id=&#34;results&#34;&gt;Results&lt;/h3&gt;
&lt;p&gt;The first time we looked at the analytics following the responsive conversion, we were &lt;strong&gt;shocked&lt;/strong&gt;! Using a small sample period, from just a year prior, we saw a &lt;strong&gt;280%&lt;/strong&gt; increase in mobile purchases.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/07/case-study-responsive-design-return-on/image-0.png&#34; /&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;The timeframe for these comparison numbers was August 2014 before the responsive transition and August of 2015, after the transition.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To sanity check those numbers, we just re-ran some of the analytics recently and in May of 2016, revenue from mobile users is still up over 90% and &lt;strong&gt;the clients total revenue year-over-year is up 12%&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/07/case-study-responsive-design-return-on/image-1.png&#34; /&gt;&lt;/div&gt;
&lt;p&gt;We also ran some numbers on the growth of mobile revenue as a percentage of overall revenue through this process. As you can see, two years ago mobile revenue was less than 1% and is now near 12%.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img src=&#34;/blog/2016/07/case-study-responsive-design-return-on/image-2.jpeg&#34; /&gt;&lt;/div&gt;
&lt;p&gt;In this case, I didn’t go into all the ways to slice and dice the numbers in Google Analytics. However I&amp;rsquo;m happy to speak with you if you want to know more about mobile users, this client’s data, or how responsive design might help grow your e-commerce business.&lt;/p&gt;
&lt;h3 id=&#34;the-lesson&#34;&gt;The Lesson&lt;/h3&gt;
&lt;p&gt;The lesson here is that any store will benefit from going responsive. Having an experienced partner like End Point that can work with your budget and timeline can make this is a doable project for any size store and budget.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Hue’s on First: How we used responsive bulbs to join software and hardware for a busy medical practice</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/03/hues-on-first/"/>
      <id>https://www.endpointdev.com/blog/2016/03/hues-on-first/</id>
      <published>2016-03-14T00:00:00+00:00</published>
      <author>
        <name>Liz Flyntz</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/hues-on-first/FastTrackoffice.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;In 2014 we began working with a busy bariatric surgery office in Long Island to create a system that would allow the practice to better manage doctor paging and patient wait time. By placing a responsive, color-coded light bulb and tablet outside each examination room, the staff could see which rooms were empty, which were occupied by a patient waiting on a specific doctor, and in which a doctor-patient consultation was in process. Outside each room is a tablet with information including the patient number, the attending doctor’s name, and the wait time.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/hues-on-first/FastTrackmapmonitor.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;In addition to providing a comprehensive, granular paging service for doctors, Fast Track also provides feedback to the practice. This feedback includes average patient wait times per doctor, per time of day, and per procedure. This allows the practice to make necessary changes and increase patient satisfaction and peace of mind.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/03/hues-on-first/FastTrackapp.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;I asked Danny Divita, one of the main developers on this project, to tell us more about the &lt;a href=&#34;http://www2.meethue.com/en-us/&#34;&gt;Hue&lt;/a&gt;/ &lt;a href=&#34;https://web.archive.org/web/20180107115334/http://www.fasttrackmed.com/&#34;&gt;FastTrack&lt;/a&gt; interface.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: Describe the project for which we used Hue bulbs. What were all the pieces that needed fitting together?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: The Hue bulbs are being used for a bariatric clinic to alert the staff when pages are sent to of pages to specific rooms. Alongside the lights the API also has to work with a RF device-locating API. The RF API had to be coordinated with the Hue light API to coordinate changing colors, alerts, and states.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: Why were Hue bulbs a good solution for the problem of creating an easy-to-understand, integratable visual alert system? Did you consider any alternatives?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: From a cost perspective and ease of integration the bulbs were a good solution for this project. There are other solutions, but they are more costly and the integration would have taken longer.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: How did you hear about Hue bulbs? Was the API easy to access and work with? How was using Hue’s testing environment?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: The client suggested the bulbs during their research before having us develop their application. The API is extremely easy to work with and well documented. The Hue API has a built-in testing feature that made it easy to understand the API and develop around it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: What was the most difficult thing about integrating this technology? Can you think of any other commercial implementations of these bulbs? Specifically in the medical industry?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: The most difficult aspect was trying to come up with a good alert (blinking) feature. The API has some built in alerts, but they are limited to a set timed interval. We had to develop around this to ensure the alerts stayed constant and did not time out. Another application for these lights in the medical field could be to indicate severity of a situation or condition. Because the lights can change color, the applications can signal the proper response for the staff.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;LF: Did you write any new software for this project? Is that work available to other developers?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DD: We used a third party library that helps to manage stateless workflows. Our application expanded upon this library to design a workflow engine that manages paging the staff, Hue lights, and RF device locating.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Full Screen Gallery with Supersized and video slides</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/01/full-screen-gallery-with-supersized-and/"/>
      <id>https://www.endpointdev.com/blog/2016/01/full-screen-gallery-with-supersized-and/</id>
      <published>2016-01-26T00:00:00+00:00</published>
      <author>
        <name>Marina Lohova</name>
      </author>
      <content type="html">
        &lt;p&gt;I was recently looking to build a full screen image and video gallery for our client &lt;a href=&#34;https://mission-blue.org/&#34;&gt;Mission Blue&lt;/a&gt;. Something similar to the Google Maps interface you can see in the screenshot below:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;    &lt;a href=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;       &lt;img border=&#34;0&#34; src=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-0.png&#34; width=&#34;600&#34;/&gt;     &lt;/a&gt;   &lt;/div&gt;
&lt;p&gt;After scouring the Internet to find a suitable jQuery plugin I finally decided on &lt;a href=&#34;https://web.archive.org/web/20170629183603/http://buildinternet.com/2009/05/supersized-20-full-screen-imagebackground-slideshow-jquery-plugin-w-transitions-and-controls/&#34;&gt;Supersized, Full screen background slideshow plugin for jQuery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After downloading the library, include it on the page:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;link&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;href&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-content/plugins/wp-supersized/theme/supersized.shutter.css?ver=4.2.2&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;supersized_theme_css-css&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;media&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;all&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;rel&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;link&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-includes/js/jquery/ui/effect.min.js?ver=1.11.4&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-content/plugins/wp-supersized/js/jquery.easing.min.js?ver=1.3&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-content/plugins/wp-supersized/js/jquery.easing.compatibility.js?ver=1.0&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/wp-content/plugins/wp-supersized/js/jquery.animate-enhanced.min.js?ver=0.75&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;text/javascript&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;/wp-content/plugins/wp-supersized/js/supersized.3.2.7.min.js?ver=3.2.7&amp;#39;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;basic-functionality&#34;&gt;Basic functionality&lt;/h3&gt;
&lt;p&gt;Let’s create a variable that will hold all the images in the slideshow:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; images = [];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;images.push({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  type: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;IMAGE&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  image: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;img1.jpg&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  title: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;Image 1&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thumb: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;img1_thumb.jpg&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  url: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;https://www.endpointdev.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;images.push({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  type: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;YOUTUBE&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  image: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;screenshot1.jpg&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  title: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;YouTube slide&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  videoid: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;abc12345678&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thumb: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;screenshot1_thumb.jpg&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  url: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;https://www.youtube.com/watch?v=abc12345678&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s initialize Supersized:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jQuery.supersized({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  slideshow: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  autoplay: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  min_width: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  min_height: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  vertical_center: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  horizontal_center: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fit_always: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fit_portrait: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fit_landscape: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  slide_links: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;blank&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thumb_links: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  thumbnail_navigation: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  slides: images,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mouse_scrub: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;customizing-the-toolbar&#34;&gt;Customizing the toolbar&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;thumb-tray&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;load-item&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;thumb-back&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;thumb-forward&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;slidecaption&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;customizing-the-screen-image-size&#34;&gt;Customizing the screen image size&lt;/h3&gt;
&lt;p&gt;I didn’t want to have the full screen image as it was a little overwhelming for the user. I wanted the black bars just like in the Google interface. Supersized allows for easy customization. This CSS did the trick:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;supersized&lt;/span&gt;, #&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;supersized&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;li&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;width&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;70&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;left&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;right&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;top&lt;/span&gt;: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;px&lt;/span&gt; &lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;!important&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;margin&lt;/span&gt;:&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;introducing-video-youtube-slides&#34;&gt;Introducing video (YouTube) slides&lt;/h3&gt;
&lt;p&gt;First, I added the Youtube API:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;https://www.youtube.com/iframe_api&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then I added a couple of CSS styles:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;supersized&lt;/span&gt; .&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;player&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;margin&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;block&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, I went into the Supersized library source and modified it. To allow for the video slides to appear, I added the new condition and the slide type &amp;lsquo;YOUTUBE&amp;rsquo;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;base._renderSlide = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(loadPrev, options) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; linkTarget = base.options.new_window ? &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39; target=&amp;#34;_blank&amp;#34;&amp;#39;&lt;/span&gt; : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; imageLink = (base.options.slides[loadPrev].url) ? &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;href=&amp;#39;&amp;#34;&lt;/span&gt; + base.options.slides[loadPrev].url + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; slidePrev = base.el + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39; li:eq(&amp;#39;&lt;/span&gt; + loadPrev + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; imgPrev = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;img src=&amp;#34;&amp;#39;&lt;/span&gt; + base.options.slides[loadPrev].image + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#34;/&amp;gt;&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (base.options.slides[loadPrev].type == &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;YOUTUBE&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imgPrev.load(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; video = $(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;div class=&amp;#34;player&amp;#34; id=&amp;#34;player&amp;#39;&lt;/span&gt;+ base.options.slides[loadPrev].videoid + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;#34;&amp;gt;&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      video.appendTo(slidePrev);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; player = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;new&lt;/span&gt; YT.Player(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;player&amp;#39;&lt;/span&gt; + base.options.slides[loadPrev].videoid, {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        height: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;390&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        width: &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;640&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        videoId: base.options.slides[loadPrev].videoid
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&lt;span style=&#34;color:#888&#34;&gt;// End Load
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imgPrev.appendTo(slidePrev).wrap(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;lt;a &amp;#39;&lt;/span&gt; + imageLink + linkTarget + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&amp;gt;&amp;lt;/a&amp;gt;&amp;#39;&lt;/span&gt;).parent().parent().addClass(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;image-loading &amp;#39;&lt;/span&gt; + options[&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;class&amp;#39;&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imgPrev.load(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).data(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;origWidth&amp;#39;&lt;/span&gt;, $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).width()).data(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;origHeight&amp;#39;&lt;/span&gt;, $(&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;this&lt;/span&gt;).height());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      base.resizeNow();&lt;span style=&#34;color:#888&#34;&gt;// Resize background image
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;    });&lt;span style=&#34;color:#888&#34;&gt;// End Load
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;final-result&#34;&gt;Final Result&lt;/h3&gt;
&lt;p&gt;This is how gallery looks with the customizations:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;  &lt;a href=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-1-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;     &lt;img border=&#34;0&#34; src=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-1.png&#34; width=&#34;600&#34;/&gt;   &lt;/a&gt; &lt;/div&gt;
&lt;p&gt;This is what a video slide looks like:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;  &lt;a href=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-2-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;     &lt;img border=&#34;0&#34; src=&#34;/blog/2016/01/full-screen-gallery-with-supersized-and/image-2.png&#34;/&gt;   &lt;/a&gt; &lt;/div&gt;
&lt;p&gt;Hope you found this writeup useful!&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Design for the Quotidian. Build for the 100-Year Flood.</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/01/design-for-the-quotidian-build-for-the-100-year-flood/"/>
      <id>https://www.endpointdev.com/blog/2016/01/design-for-the-quotidian-build-for-the-100-year-flood/</id>
      <published>2016-01-13T00:00:00+00:00</published>
      <author>
        <name>Jonathan Blessing</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/01/design-for-the-quotidian-build-for-the-100-year-flood/100YearFlood.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;After years of building software, I’ve crossed over to the design side and spent the last months thinking about &lt;a href=&#34;http://www.uxisnotui.com&#34;&gt;UI/UX&lt;/a&gt;. In doing so I’ve come to realize that as disciplines, engineering and designing are far afield. Software development challenges you to think of the worst and least likely, whereas design asks you to consider the everyday essence of the thing.&lt;/p&gt;
&lt;p&gt;Floods are uncommon, otherwise someone would have knowingly built your home in a river. Floods are what software developers call edge cases, uncommon happenings, and they are the subject of worry for software developers. They are what we build for. What happens when a user accidentally dumps Moby Dick into the field labeled “First Name”? Or, what happens when the hackers come calling; what weakness will they find?&lt;/p&gt;
&lt;p&gt;As users of software, people mostly behave as expected, but not always. Like a city planner preparing for a 100-year flood, software developers carefully consider unlikely events—​especially when building for large organizations, the Internet, or for a long lifespan. In the fullness of time, all events inhere. The unusual will happen, which is to say that software not engineered for edge cases is eventually hacked, produces inaccuracies, or simply fails. Just as the 100-year flood will in time arrive downtown, so too do the hackers, the accidents, and the failures. And knowing this, uncommon eventualities often come to define a project. (As an example, consider the extreme, &lt;a href=&#34;https://www.scientificamerican.com/article/shaping-up-10-engineering-and-design-facts-about-one-world-trade-center/&#34;&gt;One World Trade Center&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;While software may appear to be about banking, chatting, or auctions, it is really about surviving the crazy things users might do. Designers, on the other hand, don’t care about your crazy. They care for expressing the purpose of the thing. Which is to say, they are designing for everyday use, the common cases, for what the thing is supposed to do. As such, design ensures that things look like what they are about. And, that means mostly ignoring how the thing may be misused.&lt;/p&gt;
&lt;p&gt;I’m thinking of a butter knife, and how it is so often a poor substitute for a flathead screwdriver. A nicely designed butter knife announces its function, even at the expense of limiting its utility. The designer of the butter knife doesn’t care that the tip is without the torsional rigidity to help you unwind that screw. He cares that it looks like a thing for cutting and spreading butter.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/01/design-for-the-quotidian-build-for-the-100-year-flood/butterknife.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;UI/UX design is the same. A well designed application promotes its purpose, instructs, and looks the part. If common use cases require visiting menus labeled “Advanced”, that’s evidence that the designer missed the point of the software. The discipline of design requires us to rank order the software’s primary functions and subsidiary functions. Then we shape the look of the software to preferentially serve the most important functions, the common cases of use. If engineers build from the edges in, designers design from the center out, first thinking of the essential functions. While the developer fortifies the edges, the designer greases the rails so that the application smoothly satisfies the common cases. While engineers ensure the house won’t be washed away by a flood, designers give its layout order and harmony.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Old Dog &amp; New Tricks — Giving Interchange a New Look with Bootstrap</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/09/old-dog-new-tricks-giving-interchange/"/>
      <id>https://www.endpointdev.com/blog/2015/09/old-dog-new-tricks-giving-interchange/</id>
      <published>2015-09-02T00:00:00+00:00</published>
      <author>
        <name>Greg Hanson</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;So your &lt;a href=&#34;http://www.icdevgroup.org&#34;&gt;Interchange&lt;/a&gt; based website looks like it walked out of a disco&amp;hellip; but you spent a fortune getting the back end working with all those custom applications&amp;hellip;. what to do?&lt;/p&gt;
&lt;p&gt;Interchange is currently being used in numerous very complex implementations. Trying to adapt another platform to replace Interchange is a formidable task, and in many cases the “problem” that users are trying to “solve” by replacing Interchange, can be remedied by a relatively simple face lift to the front end. One of the main attractions to Interchange in the past was its ability to scale from a small mom &amp;amp; pop eCommerce application, to a mid level support system for a larger company and its related back end systems. Once the connection to those back end systems has been created, and for as long as you use those related systems, Interchange will continue to be the most economic choice for the job. But that leaves the front end, the one that your customers see and use (with their phones and tablets) that becomes the most immediate target for “modernization”.&lt;/p&gt;
&lt;p&gt;Granted, there are new and alternate ways of accessing and presenting data and views to users, but many of those alternatives are also accessible and inter-operable with Interchange. So while there are several topics that can be investigated at length, we will focus first on a popular front end framework that can help Interchange present a modern responsive theme to the end users. That framework is &lt;a href=&#34;http://getbootstrap.com/&#34;&gt;Bootstrap&lt;/a&gt;. Bootstrap is a good basic start for breathing new life into your Interchange application. Bootstrap uses a reasonably generic approach to HTML, CSS, and JavaScript frameworking. This blends nicely with the Interchange application approach: providing a basic, repeatable, broad based and well supported foundation that can then be crafted into whatever the developer and their client may need.&lt;/p&gt;
&lt;p&gt;My intent in this post, is to give you links to the tools available to implement Bootstrap into your Interchange application, and in subsequent posts explain our development process which may help you in how you use the tools.  Like any development, there are many ways to accomplish various tasks, and knowing why certain things were done, can help.&lt;/p&gt;
&lt;p&gt;Alternatively, you may simply want to just download the “strap” catalog, and get started. At the time of this writing, Josh Lavin has been reviewing and refining the package, and the most recent version can be found at his Github account: &lt;a href=&#34;https://github.com/jdigory/strap&#34;&gt;Bootstrap template for Interchange&lt;/a&gt;. It will soon become the standard catalog template in Interchange. So, if you are not really interested in why and how this template was developed, feel free to go to the git repository in the link, clone a copy and get busy!  The &lt;a href=&#34;https://github.com/jdigory/strap/blob/master/README.md&#34;&gt;README&lt;/a&gt; is very informative, and if you are an Interchange developer you probably won’t have much trouble implementing this.&lt;/p&gt;
&lt;p&gt;If you are interested in some of the major changes that we made to the old “standard” templating approach, and how you can apply those changes to an existing catalog without having to start from scratch, stay tuned in for my next post.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Mobile-friendly sites or bust!</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/03/mobile-friendly-sites-or-bust/"/>
      <id>https://www.endpointdev.com/blog/2015/03/mobile-friendly-sites-or-bust/</id>
      <published>2015-03-23T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;A few weeks ago, &lt;a href=&#34;http://googlewebmastercentral.blogspot.com/2015/02/finding-more-mobile-friendly-search.html&#34;&gt;Google announced that&lt;/a&gt; starting on April 21 it will expand its “use of mobile-friendliness as a ranking signal” which “will have a significant impact in our search results”.&lt;/p&gt;
&lt;p&gt;The world of search engine optimization and online marketing is aflutter about this announcement, given that even subtle changes in Google’s ranking algorithm can have major effects to improve or worsen any particular site’s ranking. And the announcement was made less than two months in advance of the announced date of the change, so there is not much time to dawdle.&lt;/p&gt;
&lt;p&gt;Google has lately been increasing its pressure on webmasters (is that still a real term‽) such as with its announcement last fall of an accelerated timetable for &lt;a href=&#34;https://security.googleblog.com/2014/09/gradually-sunsetting-sha-1.html&#34;&gt;sunsetting SSL certificates with SHA-1 signatures&lt;/a&gt;. So far these accelerated changes have been a good thing for most people on the Internet.&lt;/p&gt;
&lt;p&gt;In this case, Google provides an easy &lt;a href=&#34;https://www.google.com/webmasters/tools/mobile-friendly/&#34;&gt;Mobile-Friendly Site Test&lt;/a&gt; that you can run on your sites to see if you need to make changes or not:&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;a href=&#34;https://www.google.com/webmasters/tools/mobile-friendly/&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2015/03/mobile-friendly-sites-or-bust/image-0.png&#34;/&gt;&lt;/a&gt;&lt;br/&gt; &lt;/div&gt;
&lt;p&gt;So get on it and check those sites! I know we have a few that we can do some work on.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Angular Responsive Layout Directive</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/01/angular-responsive-layout-directive/"/>
      <id>https://www.endpointdev.com/blog/2015/01/angular-responsive-layout-directive/</id>
      <published>2015-01-13T00:00:00+00:00</published>
      <author>
        <name>Marina Lohova</name>
      </author>
      <content type="html">
        &lt;p&gt;To all of you window.onResize aficionados, I dedicate this blog post because today we will be doing a lot of dynamic resizing in JavaScript. All of it will be done completely and effortlessly with my one-page long Angular directive.&lt;/p&gt;
&lt;p&gt;Why do I need to attach an expensive onResize handler to my already overloaded page, you ask. The answer is very simple. Our app layout is pixel-perfect. Each element has the predefined width and margins. Yet, the app needs to look good on all kind of devices, from regular PC to tablet to iPhone. That’s why I created the following Angular directive in /scripts/directives/tsResize.js:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;angular.module(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;angularApp&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.directive(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;tsResize&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;($window) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt;(scope, element) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;var&lt;/span&gt; w = angular.element($window);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   scope.getWindowDimensions = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;h&amp;#39;&lt;/span&gt;: $window.innerHeight,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;: $window.innerWidth
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   scope.$watch(scope.getWindowDimensions,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; (newValue, oldValue) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     scope.windowHeight = newValue.h;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     scope.windowWidth = newValue.w;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     scope.mainContainerStyle = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (newValue.w &amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;890&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         val = newValue.w/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;890&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-webkit-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-o-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-ms-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;transform-origin&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;left -10px&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-webkit-transform-origin&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;left -10px&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     scope.topBarStyle = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (newValue.w &amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;890&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         val = newValue.w/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;890&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-webkit-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-o-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-ms-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;transform-origin&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;0 2px 0&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-webkit-transform-origin&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;0 2px 0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   w.bind(&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;resize&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     scope.$apply();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see all the magic is done with transform:scale CSS attribute on the two of my main page components: the navigation and the contents container.&lt;/p&gt;
&lt;p&gt;They styles are cross-browser.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-webkit-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-o-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-ms-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It’s important to set transform-origin, or the elements will be weirdly positioned on the page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;transform-origin&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;0 top&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-webkit-transform-origin&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;0 top&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The style calculations are attached to the changes of window dimensions.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;scope.getWindowDimensions = &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;h&amp;#39;&lt;/span&gt;: $window.innerHeight,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;: $window.innerWidth
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;scope.$watch(scope.getWindowDimensions,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;function&lt;/span&gt; (newValue, oldValue) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Few other things. My layout was sliced to the fixed width of 890px, that’s why I took 890 as the pivotal point of my scale ratio formula. You should take the default width of the layout as the base of your calculation.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (newValue.w &amp;gt; &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;890&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  val = newValue.w/&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;890&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;-webkit-transform&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;scale(&amp;#39;&lt;/span&gt; + val + &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the directive in place it’s time to plug it in:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;scripts/directives/tsResize.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;nav&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;ng-style&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;topBarStyle()&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;ts-resize&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;nav&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;ng-style&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;mainContainerStyle()&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;ng-view&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;ts-resize&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Be sure to use style “display:block” or “display:inline-block” and “position:relative” for all the inside components of the scaled elements with the default display. Otherwise they do not obey the scaling enforcement and grow way too long prompting a scrollbar.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;main-container&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;inner-block&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#369&#34;&gt;style&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;position:relative; display:inline-block&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It all worked nicely and I was able to enjoy the smoothly resizing layout.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>CSSConf US 2014 — Part One</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/05/cssconf-us-2014-part-one/"/>
      <id>https://www.endpointdev.com/blog/2014/05/cssconf-us-2014-part-one/</id>
      <published>2014-05-28T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;geeks-in-paradise&#34;&gt;Geeks in Paradise&lt;/h3&gt;
&lt;img alt=&#34;IMG 2414&#34; border=&#34;0&#34; height=&#34;450&#34; src=&#34;/blog/2014/05/cssconf-us-2014-part-one/image-0.jpeg&#34; title=&#34;IMG_2414.jpg&#34; width=&#34;600&#34;/&gt;
&lt;p&gt;Today I was very lucky to once again attend &lt;a href=&#34;https://2014.cssconf.com/&#34;&gt;CSSConf US&lt;/a&gt; here in &lt;a href=&#34;https://maps.app.goo.gl/VCRCDbanvNCzCS3a8&#34;&gt;Amelia Island, Florida&lt;/a&gt;. &lt;a href=&#34;http://www.stubbornella.org/content/&#34;&gt;Nicole Sullivan&lt;/a&gt; and crew did an excellent job of organizing and curating a wide range of talks specifically geared toward CSS developers. Although I work daily on many aspects of the web stack, I feel like I’m one of the (seemingly) rare few who actually enjoy writing CSS so it was a real treat to spend the day with many like-minded folks.&lt;/p&gt;
&lt;h3 id=&#34;styleguide-driven-development&#34;&gt;Styleguide Driven Development&lt;/h3&gt;
&lt;p&gt;Nicole Sullivan started things off with her talk on Style Guide Driven Development (SGDD). She talked about the process and challenges she and the team at &lt;a href=&#34;https://pivotal.io/labs&#34;&gt;Pivotal Labs&lt;/a&gt; went through when they redesigned the &lt;a href=&#34;https://docs.cloudfoundry.org/devguide/&#34;&gt;Cloud Foundry Developer Console&lt;/a&gt; and how they overcame many of them with the SGDD approach. The idea behind SGDD is to catalog all of the reusable components used in a web project so developers use what’s already there rather than reinventing the wheel for each new feature. The components are displayed in the style guide next to examples of the view code and CSS which makes up each component. The benefits of this approach include enabling a short feedback loop for project managers and designers and encouraging developers who may not be CSS experts to follow the “blessed” path to build components that are consistent and cohesive with the design. In Nicole’s project they were also able to significantly reduce the amount of unused CSS and layouts once they had broken down the app into reusable components.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://trulia.github.io/hologram/&#34;&gt;Hologram&lt;/a&gt; is an interesting tool to help with the creation of style guides which Nicole shared and is definitely worth checking out.&lt;/p&gt;
&lt;h3 id=&#34;sara-soueidan--styling-and-animating-scalable-vector-graphics-with-css&#34;&gt;Sara Soueidan — Styling and Animating Scalable Vector Graphics with CSS&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;http://sarasoueidan.com/&#34;&gt;Sara&lt;/a&gt; talked to us about using &lt;a href=&#34;https://en.wikipedia.org/wiki/Scalable_Vector_Graphics&#34;&gt;SVG&lt;/a&gt; with CSS and included some really neat demos. Adobe Illustrator, &lt;a href=&#34;https://inkscape.org/en/&#34;&gt;Inkscape&lt;/a&gt; and &lt;a href=&#34;https://bohemiancoding.com/sketch/&#34;&gt;Sketch 3&lt;/a&gt; are the commonly used tools used to create SVG images. Once you have your SVG image you can use the &lt;a href=&#34;https://web.archive.org/web/20150218125407/http://petercollingridge.appspot.com/svg-editor&#34;&gt;SVG Editor&lt;/a&gt; by Peter Collingridge or &lt;a href=&#34;https://github.com/svg/svgo&#34;&gt;SVGO&lt;/a&gt; (node.js based tool) to clean up and optimize the SVG code. After the cleanup and optimization you can replace the generic CSS class names from your SVG creation app with more semantic CSS class names.&lt;/p&gt;
&lt;p&gt;There are a variety of ways to include SVG on a page and Sara went over the pros and cons of each. The method that seemed most interesting to me was to use an &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt; tag which allowed for a fallback image for browsers that do not support SVG. Sara mapped out the subset of CSS selectors which can be used to target SVG elements, how to “responsify” SVGs and to animate SVG paths. Be sure to check out &lt;a href=&#34;https://docs.google.com/presentation/d/1Iuvf3saPCJepVJBDNNDSmSsA0_rwtRYehSmmSSLYFVQ/present#slide=id.p&#34;&gt;her slides&lt;/a&gt; from the talk.&lt;/p&gt;
&lt;h3 id=&#34;lea-verou--the-chroma-zone-engineering-color-on-the-web&#34;&gt;Lea Verou — The Chroma Zone: Engineering Color on the Web&lt;/h3&gt;
&lt;p&gt;Lea’s talk was about color on the web. She detailed the history of how color has been handled up to this point, how it works today and some of the interesting color-related CSS features which are coming in the future. She demonstrated how each of the color spaces have a geographical representation (e.g. RGB can be represented as a cube and HSL as a double-cone) which I found neat. RGB is very unintuitive when it comes to choosing colors. HSL is much more intuitive but has some challenges of its own. The new and shiny CSS color features Lea talked about included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;filters&lt;/li&gt;
&lt;li&gt;blending modes&lt;/li&gt;
&lt;li&gt;CSS variables&lt;/li&gt;
&lt;li&gt;gray()&lt;/li&gt;
&lt;li&gt;color() including tint, shade and other adjusters&lt;/li&gt;
&lt;li&gt;the #rgba and #rrggbbaa notation&lt;/li&gt;
&lt;li&gt;hwb()&lt;/li&gt;
&lt;li&gt;named hues and &lt;angle&gt; in hsl()&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of these new features can be used already via libs like &lt;a href=&#34;https://www.bourbon.io/&#34;&gt;Bourbon&lt;/a&gt; and &lt;a href=&#34;http://www.myth.io/&#34;&gt;Myth&lt;/a&gt;. Check out the &lt;a href=&#34;http://leaverou.github.io/chroma-zone/&#34;&gt;Chroma Zone: Engineering Color on the Web&lt;/a&gt; slides to learn more.&lt;/p&gt;
&lt;h3 id=&#34;c&#34;&gt;C$$&lt;/h3&gt;
&lt;p&gt;I will write up more of the talks soon but wanted to thank &lt;a href=&#34;https://web.archive.org/web/20140207090237/http://madeby.jennschiffer.com/&#34;&gt;Jenn Schiffer&lt;/a&gt; for keeping us all laughing throughout the day in her role as MC and topping it off with a hilarious, satirical talk of her own. Thanks also to &lt;a href=&#34;https://alexsexton.com/&#34;&gt;Alex&lt;/a&gt; and &lt;a href=&#34;http://ajpiano.com/&#34;&gt;Adam&lt;/a&gt; for curating the music and looking after the sound.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Mobile Emulation in Chrome DevTools</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/01/mobile-emulation-in-chrome-devtools/"/>
      <id>https://www.endpointdev.com/blog/2014/01/mobile-emulation-in-chrome-devtools/</id>
      <published>2014-01-24T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;p&gt;I have been doing some mobile development lately and wanted to share the new Mobile Emulation feature in Chrome Canary with y’all. &lt;a href=&#34;https://www.google.ca/intl/en/chrome/browser/canary.html&#34;&gt;Chrome Canary&lt;/a&gt; is a development build of Chrome which gets updated daily and gives you the chance to use the latest and greatest features in Chrome. I’ve been using it as my primary browser for the past year or so and it’s been fairly stable. What’s great is that you can run Chrome Canary side-by-side with the stable release version of Chrome. For the odd time I do have issues with stability etc., I can just use the latest stable Chrome and be on my way. If you need more convincing, Paul Irish’s &lt;a href=&#34;http://www.paulirish.com/2012/chrome-canary-for-developers/&#34;&gt;Chrome Canary for Developers&lt;/a&gt; post might be helpful.&lt;/p&gt;
&lt;p&gt;I should mention that Chrome Canary is only available for OS X and Windows at this point. I tested &lt;a href=&#34;http://www.chromium.org/getting-involved/dev-channel#TOC-Linux&#34;&gt;Dev channel Chromium&lt;/a&gt; on Ubuntu 13.10 this afternoon and the new mobile emulation stuff is not ready there yet. It should not be long though.&lt;/p&gt;
&lt;h3 id=&#34;mobile-emulation-in-chrome-dev-tools&#34;&gt;Mobile Emulation in Chrome Dev Tools&lt;/h3&gt;
&lt;img alt=&#34;Mobile emulation chrome canary&#34; border=&#34;0&#34; height=&#34;334&#34; src=&#34;/blog/2014/01/mobile-emulation-in-chrome-devtools/image-0.png&#34; title=&#34;mobile-emulation-chrome-canary.png&#34; width=&#34;559&#34;/&gt; 
&lt;p&gt;Once enabled, the Emulation panel shows up in the Dev Tools console drawer. It gives you the option of emulating a variety devices (many are listed in the drop-down) and you also have the ability to fine tuning the settings à la carte. If you choose to emulate the touchscreen interface the mouse cursor will change and operate like a touch interface. Shift+drag allows you to pinch and zoom. There are some cool features for debugging and inspecting touch events as well.&lt;/p&gt;
&lt;h3 id=&#34;learning-more&#34;&gt;Learning More&lt;/h3&gt;
&lt;p&gt;If you would like to learn more, be sure to check out the &lt;a href=&#34;https://developers.google.com/chrome-developer-tools/docs/mobile-emulation&#34;&gt;Mobile emulation documentation&lt;/a&gt; at the Chrome DevTools docs site.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>CSS Conf 2013 — When Bootstrap Attacks!</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/06/css-conf-2013-when-bootstrap-attacks/"/>
      <id>https://www.endpointdev.com/blog/2013/06/css-conf-2013-when-bootstrap-attacks/</id>
      <published>2013-06-03T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;img alt=&#34;Cssconf 2013&#34; border=&#34;0&#34; height=&#34;234&#34; src=&#34;/blog/2013/06/css-conf-2013-when-bootstrap-attacks/image-0.png&#34; style=&#34;display:block; margin-left:auto; margin-right:auto;&#34; title=&#34;cssconf-2013.png&#34; width=&#34;373&#34;/&gt;
&lt;p&gt;I attended the inaugural &lt;a href=&#34;https://web.archive.org/web/20130629170825/http://cssconf.com/speakers.html&#34;&gt;CSS Conf&lt;/a&gt; last week at Amelia Island, Florida. The conference was organized by &lt;a href=&#34;http://www.stubbornella.org/&#34;&gt;Nicole Sullivan&lt;/a&gt;, &lt;a href=&#34;http://brett.stimmerman.com/&#34;&gt;Brett Stimmerman&lt;/a&gt;, &lt;a href=&#34;https://snook.ca/&#34;&gt;Jonathan Snook&lt;/a&gt;, and &lt;a href=&#34;https://www.paulirish.com/&#34;&gt;Paul Irish&lt;/a&gt; and put on with help from a host of volunteers. The talks were presented in a single track style on a wide range of CSS-related topics; there was something interesting for everyone working in this space. I really enjoyed the conference, learned lots and had great discussions with a variety of people hacking on interesting things with CSS. In the coming days I will be blogging about some of the talks I attended and sharing what I learned, so stay tuned!&lt;/p&gt;
&lt;h3 id=&#34;when-bootstrap-attacks&#34;&gt;When Bootstrap Attacks&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;http://www.pamelafox.org/&#34;&gt;Pamela Fox&lt;/a&gt; had the opening slot and spoke about the experiences and challenges she faced when upgrading &lt;a href=&#34;https://getbootstrap.com/2.3.2/&#34;&gt;Bootstrap&lt;/a&gt; to V2 in a large web app (&lt;a href=&#34;https://www.coursera.org/&#34;&gt;Coursera&lt;/a&gt;). What she initially thought would be a quick project turned into a month-long “BOOTSTRAPV2ATHON”. Bootstrap styles were used throughout the project in dozens of PHP, CSS and JavaScript files. The fact that Bootstrap uses generic CSS class names like “alert”, “btn”, error etc made it very difficult to grep through the codebase for them. The Bootstrap classes were also used as hooks by the project’s JavaScript application code.&lt;/p&gt;
&lt;h3 id=&#34;lessons-learned&#34;&gt;Lessons Learned&lt;/h3&gt;
&lt;p&gt;Fox offered some tips for developers facing a similar situation. The first of which was to prefix the Bootstrap CSS classes (e.g. .tbs-alert) in order to decouple Bootstrap from the customizations in your project. Some requests have been made to the Bootstrap team on this front but the issue has not been addressed yet. In the meantime, devs can add a task to their build step (e.g. &lt;a href=&#34;https://gruntjs.com/&#34;&gt;Grunt&lt;/a&gt;, the asset pipeline in Rails etc) to automate the addition of prefixes to each of the CSS classes.&lt;/p&gt;
&lt;p&gt;Another tip is to avoid using Bootstrap CSS classes directly. Instead, use the “extend” functionality in your preprocessor (Sass, Less, Stylus etc) of choice. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  .ep-btn {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @extend .btn
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;amp;:hover {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          @extend .btn:hover
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This way your project can extend the Bootstrap styles but keep your customizations separate and not closely coupled to the framework.&lt;/p&gt;
&lt;p&gt;The same logic should also be applied to the JavaScript in your project. Rather than using the Bootstrap class names as hooks in your JavaScript code, use a prefix (e.g. js-btn) or use HTML5 data attributes. Separating the hooks used for CSS styles from those used in JavaScript is very helpful when upgrading or swapping out a client-side framework like Bootstrap.&lt;/p&gt;
&lt;h3 id=&#34;test-all-of-the-things&#34;&gt;Test All Of The Things&lt;/h3&gt;
&lt;p&gt;Pamela wrapped up the talk by explaining how testing front end code would ease the pain of upgrading a library next time. There are many testing libraries available today which address some of these concerns. She mentioned &lt;a href=&#34;https://mochajs.org/&#34;&gt;mocha&lt;/a&gt;, &lt;a href=&#34;http://www.chaijs.com/&#34;&gt;Chai&lt;/a&gt;, &lt;a href=&#34;https://github.com/jsdom/jsdom&#34;&gt;jsdom&lt;/a&gt; and &lt;a href=&#34;https://docs.seleniumhq.org/&#34;&gt;Selenium&lt;/a&gt; which all look very helpful. In addition to testing front end code she offered up the idea of “diffing your front end” in a visual way. This concept was very interesting to someone who ensures designs are consistent across a wide array of browsers and devices on a daily basis.
&lt;img alt=&#34;Diff your front end&#34; border=&#34;0&#34; height=&#34;341&#34; src=&#34;/blog/2013/06/css-conf-2013-when-bootstrap-attacks/image-1.png&#34; style=&#34;display:block; margin-left:auto; margin-right:auto;&#34; title=&#34;diff-your-front-end.png&#34; width=&#34;559&#34;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/python-needle/needle&#34;&gt;Needle&lt;/a&gt; is a tool which allows you to do this &lt;em&gt;automatically&lt;/em&gt;. Once you develop a test case, you can run Needle to view a visual diff of your CSS changes. I think this is an excellent idea. Pamela also noted that the combination of &lt;a href=&#34;https://support.mozilla.org/en-US/questions/940991&#34;&gt;Firefox screenshots&lt;/a&gt; and &lt;a href=&#34;https://www.kaleidoscopeapp.com/&#34;&gt;Kaleidoscope&lt;/a&gt; could be used manually in much the same way.&lt;/p&gt;
&lt;p&gt;Many thanks to &lt;a href=&#34;https://twitter.com/pamelafox&#34;&gt;Pamela&lt;/a&gt; for sharing this! The slides for this talk can be viewed &lt;a href=&#34;http://slides.com/pamelafox/when-bootstrap-attacks#/&#34;&gt;here&lt;/a&gt; and the talk was recorded so the video will also be available sometime soon.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Honor your elders (and others)</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/05/honor-your-elders-and-others/"/>
      <id>https://www.endpointdev.com/blog/2013/05/honor-your-elders-and-others/</id>
      <published>2013-05-24T00:00:00+00:00</published>
      <author>
        <name>Jeff Boes</name>
      </author>
      <content type="html">
        &lt;p&gt;What an odd topic, you might be thinking. &lt;a href=&#34;/blog/2011/06/seniornet/&#34;&gt;Some time ago,&lt;/a&gt; I began teaching my elders (who are rapidly becoming my contemporaries, curse you, Father Time) how to navigate the Internet. After almost two years of this, I’ve become more sensitized to seeing the ’Net from their POV.&lt;/p&gt;
&lt;p&gt;Here’s a small fragment of a page I saw today (actual size):&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;/blog/2013/05/honor-your-elders-and-others/image-0-big.png&#34; imageanchor=&#34;1&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2013/05/honor-your-elders-and-others/image-0.png&#34;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The page numbers and arrowheads are the only navigation elements on this &lt;strong&gt;huge, complex&lt;/strong&gt; page that allow you to move around the list of products. The numbers are an 11px font, and the arrowheads are 6px by 8px. For a senior citizen, or indeed anyone with less than perfect vision and eye-hand coordination, this is pretty challenging to find on the page, let alone use.&lt;/p&gt;
&lt;p&gt;Here’s a quick challenge for you as web designer: try dimming your screen down a bit, to the point where it’s noticeably uncomfortable to use. Does your page still seem easy to navigate? Now try switching from your dominant hand to your other hand, and try clicking your page navigation elements (not just buttons, but drop-downs, menus, etc.). Still usable? If not, you may be designing your page to keep away some users. Just a thought.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
