<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel Emod Kovacs</title>
    <description>The latest articles on DEV Community by Daniel Emod Kovacs (@danielkov).</description>
    <link>https://dev.to/danielkov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F765280%2F76e11b76-f460-4ba0-8e50-54b69d9c4977.jpeg</url>
      <title>DEV Community: Daniel Emod Kovacs</title>
      <link>https://dev.to/danielkov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danielkov"/>
    <language>en</language>
    <item>
      <title>Visual Primitives and Headless UIs - a Modern UI Library Trend</title>
      <dc:creator>Daniel Emod Kovacs</dc:creator>
      <pubDate>Fri, 08 Dec 2023 17:16:08 +0000</pubDate>
      <link>https://dev.to/danielkov/visual-primitives-and-headless-uis-a-modern-ui-library-trend-19jk</link>
      <guid>https://dev.to/danielkov/visual-primitives-and-headless-uis-a-modern-ui-library-trend-19jk</guid>
      <description>&lt;p&gt;If you're wondering what a headless UI is, or what molecular physics has to do with web development, just know, that I'm just as confused as you are. Let's begin.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI Libraries
&lt;/h2&gt;

&lt;p&gt;You've probably used a UI library before. It's a set of components, usually following some common visual and technical conventions. Some are open source and some are owned and maintained by dedicated teams within tech companies. They aim to achieve the following goals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Streamline user experience by providing a common set of visual elements.&lt;/li&gt;
&lt;li&gt;Speed up development by providing a strong set of pre-made components ready to use for various use-cases.&lt;/li&gt;
&lt;li&gt;Improve both DX and UX by taking care of accessibility and usability.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By adopting a solid UI library, projects usually see and improvement in performance, usability and scalability. But how?&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;There are various performance implications of modern frontends. Bundle size is a key concern, especially for products where the customer impact of spending more time on loading customer assets can be translated to a loss of revenue, such as online stores and social media platforms. One product I worked on several years ago had a new definition for button styles for every page that loaded. The way that project was set up, a Spring Boot controller would determine the assets to send for each individual page.&lt;/p&gt;

&lt;p&gt;Colleagues at the time couldn't figure out how to send common assets, so they just duplicated every common style (the CSS) and common behaviour logic (the JavaScript - mostly jQuery + plugins). This lead to the browser having to load a large chunk of CSS and JS on every page transition. The user experience was horrible, and that's putting it lightly. It did not matter, though, as the users were all employed by the company. It was an internal application for one of the largest global delivery companies in the world. As horrible as it sounds, this is not uncommon, in fact, it is the norm.&lt;/p&gt;

&lt;p&gt;To improve upon this project, my recommendation and subsequent proof of concept included the creation of a UI library to capture all the common interactions within the application and provide stable and re-usable styles for developers to work with. I've also introduced the team to React and the concept of a framework to be used on the UI. One of our typical pages took 16 seconds to load on average. Converting this page to a single page application, using React and adding components optimised for performance brought this down to 0.4s &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/First_contentful_paint" rel="noopener noreferrer"&gt;FCP&lt;/a&gt; and the table displayed all the data the user could see in 2.1 seconds on average. Being a frontend engineer, I'm naturally not good at maths, but this seems like a pretty big improvement to me. The UI felt snappier and users were happier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development Time
&lt;/h3&gt;

&lt;p&gt;There are of course, other aspects to performance. A customer facing online video streaming platform is our next example. The core of the product - the streaming client - that generated over 90% of the revenue and provided the experience that users kept coming back for since 2001. This was no ordinary video player. Since its humble beginnings in the early 2000s, it had come very far. Over 20 different features had been integrated into this client over the years. This included things like a live chat feature, token purchase overlay and even a battle mode, where two streams would be played at once, but using the same "virtual room". Of course not all of these features would be visible at all times. Some were seasonal and some depended on various user and site attributes. Did I forget to mention, there was also a whitelabel offering of this product? This complicated things slightly.&lt;/p&gt;

&lt;p&gt;The client in question was written by very smart people some 18 years ago. It started its life as an ActionScript codebase, but was converted to &lt;a href="https://haxe.org/" rel="noopener noreferrer"&gt;Haxe&lt;/a&gt; when Apple announced the discontinuation of Flash in their browsers. Haxe is quite an exotic language. It walks like an ActionScript and talks like an ActionScript, but it gets compiled to JavaScript to be able to run in the browser. Many of Flash's original interactivity logic was replicated to support teams scrambling to convert their codebases from Flash to JavaScript. It's difficult to hire for Haxe projects and there are some limitations compared to using just JavaScript. The company decided it needed to change and I was summoned to architect this effort.&lt;/p&gt;

&lt;p&gt;One of the key difficulties of creating the right UI tools for this job was performance. This website needed to run "buttery smooth" for millions of people from hundreds of different countries on thousands of different hardware setups. Many of our users had poor internet connection and used low-end mobile devices. We've used a mobile-first approach and scaled it up to meet desktop later on. Each component had to be carefully designed and created with performance in mind. Any mistake in logic, using the wrong data structure or running unnecessary cycles could cost the company millions.&lt;/p&gt;

&lt;p&gt;My approach was the following: isolate each feature, turning the library into a core and a set of plugins. The core would authenticate and join the room. The streaming module would show you a video feed. Each feature came as its own module. The MVP was the core. It was so lean that another team even ended up using it for chat bots, running in Node.JS. Then came the best part: the UI layer. There were two types of UI components in this architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Composers&lt;/strong&gt; connected the logic to the UI. They translated core and plugin functionality into user interactions and visible state. They were aware of the application state and they used visual primitives to communicate with the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Primitives&lt;/strong&gt; are lean components. They generally consist of 1 or a few elements and their sole responsibility is styling and visuals. They know nothing about the application that uses them. You could take any of these primitives and re-use them across any other part of the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture is overkill for ordinary applications, but this was no ordinary application. Using this architecture allowed a small team to fully recreate the entire feature set in a much more performant library, using state of the art languages and tools in under a year. The usage of visual primitives wasn't as well adopted or accepted back then as it is now, but it ended up the perfect choice for the product at the time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility and Interactivity
&lt;/h3&gt;

&lt;p&gt;As sad as it is, neither of the aforementioned products placed a strong emphasis on accessibility and interactivity - two things I'm particularly passionate about. As software engineers, we usually fall under the category of "power users". I use my keyboard to navigate websites whenever possible, but unfortunately, not a lot of companies make this easy for us. I also believe that it's important to make sure that we provide the best user experience to everybody, regardless of their personal circumstances. I consider inaccessible or non-inclusive UI technical debt.&lt;/p&gt;

&lt;p&gt;This next project ticked all my boxes of a well-crafted, performant and accessible UI library. It's 2022 now and I'm sitting in my home office, propagating a change to our QA environment. I work for a multinational sports betting company in this story. We're responsible for the back-office product, that our colleagues use to interact with the betting platform. It's a low-latency, high-frequency type of application, with strong emphasis on usability. All users are power users. They need to be able to perform actions at the speed of the most exhilarating sports events and interact with thousands of data points effectively. Accessibility and interactivity are paramount.&lt;/p&gt;

&lt;p&gt;I'm propagating this change to our QA environment. It Worked on My Machine™ and I've also tested it on our previous environment, before pushing it to QA. There's two more acceptance rounds, but I'm feeling confident. It's just a small change. Only a line on my screen, it's just upticking a dependency. The dependency in question is called Ant Design. It's an all batteries included UI library for React, created by the AliPay group and powering products that generate gajillions a year. I'm only going from version 4.18.9 to 4.19. What could go wrong?&lt;/p&gt;

&lt;p&gt;A couple hours go by and our eager team of some of the best QA engineers on the market go to work. They meticulously scan every element, every feature and each pixel and colour to verify that everything aligns and the bug in question that the change was addressing was in fact fixed. And it was. But a new one also got introduced and this was a dealbreaker. Ant Design components often have an abundance of properties to customise behaviour and style. Table component alone has 98 configuration options. Even still, some things just cannot be implemented without workarounds. One of such workarounds was the addition of a form to add new data to a table. This form could be opened from a column title. We've used the &lt;code&gt;filterDropdown&lt;/code&gt; property of the table to achieve this. Ant Design, and more specifically the underlying library introduced a change that made the dropdown close on &lt;code&gt;tab&lt;/code&gt; key. This meant that the form inside the dropdown could not be properly navigated via tab key. This change silently made it to their latest version, which I then added to our project.&lt;/p&gt;

&lt;p&gt;One dreaded Slack message and a new Jira ticket later, this change came to light. I've played around with it, but ultimately had to abandon the update as I could find no maintainable workarounds to mitigate this behaviour. It was easier to manually fix the issue we wanted to address with the update than to deal with the breaking change to our UI that this introduced. This did not spark joy at all. We've had our issues with Ant Design in the past, such as a lack of sensible options for theme customisation and the impact it had on our bundle size, but we powered through it. This straw was the one that broke the camel's back. I've initiated a new project to replace Ant Design completely. But what do we replace it with? There's no real alternative to the vast amount of functionality it comes packed with. It's also very deeply integrated into our codebase. Replacing it would've meant hundreds of hours of strenuous work. We still had no candidates for replacement.&lt;/p&gt;

&lt;p&gt;I've proposed the creation of Yet Another UI Library™. This time we could go slow and take all the business needs into consideration. We could create something that addresses all of our issues with Ant Design from day one, while taking inspiration from it and others like it, to speed up development for our growing team of engineers. We also wanted to open ourselves up to the possibility to fully customise our UI. Traders who work for betting companies aren't like your average millennial. They don't want their buttons to look like frosted glass and their morphisms to skeu. When asked about interfaces they enjoyed using, they kept showing us pictures of DOS on CRT monitors. They sent us screenshots of cramped, horribly out of contrast interfaces with hundreds of different buttons and no visual hierarchy.&lt;/p&gt;

&lt;p&gt;All they cared about was being able to do what they do as fast as possible. The goal was to enable them to do just that. This library isn't tied to any specific product. Its purpose is to be used by all internal products to standardise the look, feel and UX of all internal products. It needed to promise and deliver a lot in order for it to be worthwhile adopting. Each product team had independent governance over the tech stack that was used. The only way to convince a team of adoption was through value proposition. We had to make them a deal they couldn't refuse. The deal was this: we'll design and develop an entirely new API surface for this library from scratch, based on composition and the lessons I've learnt from the design systems I've worked on previously. Composability was key for us, because it enabled the numerous product teams we had to support to implement key features independently from us. Configuration based APIs, like that of Ant Design's lack the ability to extend without hacks or the addition of further configuration.&lt;/p&gt;

&lt;p&gt;I like to talk about composition and configuration using dimensions. Configuration based approach is a two-dimensional one. You can either add or remove properties from your configuration object, factory or builder. This leaves you with limited ability when it comes to scaling your solution. It also often leads to various different types of properties being added using different paradigms, based on who implemented them. The composition based approach is a three dimensional one. You can add or remove features, but you can also extend it by stacking additional components on it. The back-end equivalent would be HTTP middleware. Rather than the server trying to know every single possible feature the user would want to add on top of it in advance, it exposes primitives and allows you - the developer - to add whatever feature you want on top of these primitives. You can even combine and re-use them. Same concept works for UI components. &lt;/p&gt;

&lt;h2&gt;
  
  
  Visual Primitives
&lt;/h2&gt;

&lt;p&gt;A visual primitive is also often referred to as an "atom". If visual particles are atoms, then sub-atomic particles are native elements, such as a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; on the web. We apply styles on top of native elements to make them look nicer and to iron out inconsistencies between different browsers. A visual primitive can't be broken down into meaningful and sensible components. Not all primitives have to employ a single native element, but they often do. Visual primitives should be simple enough to always work with each other without modifications. E.g.: placing a button inside a cell in a table should be achievable by simply rendering the two components. No workarounds should be necessary to achieve interoperability between visual primitives.&lt;/p&gt;

&lt;p&gt;Some libraries provide a set of styles via a stylesheet. These aren't visual primitives. They could be a part of a visual primitive when applied on an element. Picking the element is crucial. Adding button-like styles on a &lt;code&gt;div&lt;/code&gt; won't make it a button. You can add a click handler, but your users won't be able to interact with it the same way. It won't be focused via &lt;code&gt;tab&lt;/code&gt; key, it won't interact natively with form elements and so on. This is why picking an element is crucial in creating visual primitives.&lt;/p&gt;

&lt;p&gt;Sometimes elements aren't enough. The HTML spec has loads of elements for us to use, such as &lt;code&gt;marquee&lt;/code&gt;, &lt;code&gt;table&lt;/code&gt; and &lt;code&gt;div&lt;/code&gt;, but there are some use cases that haven't been added to the spec. &lt;code&gt;dialog&lt;/code&gt; had only recently been introduced to HTML and its API is slightly limiting as it can only be used as a modal from JavaScript via a method. Tabs don't exist natively in HTML. What if they did? How would they work? What would the API look like? I think it would be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tab&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Tab One&lt;span class="nt"&gt;&amp;lt;/tab&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tab&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"two"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Tab Two&lt;span class="nt"&gt;&amp;lt;/tab&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;content&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Content of tab one&lt;span class="nt"&gt;&amp;lt;/content&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;content&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"two"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Content of tab two&lt;span class="nt"&gt;&amp;lt;/content&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Focusing it, the screen reader would read something like: &lt;code&gt;"tab trigger, opens Tab One"&lt;/code&gt;. Pressing &lt;code&gt;tab&lt;/code&gt; key would allow users to navigate between the two tabs natively. Pressing &lt;code&gt;space&lt;/code&gt; or &lt;code&gt;enter&lt;/code&gt; key would select the currently active tab. Selecting a tab would make it "active". In the DOM, &lt;code&gt;content&lt;/code&gt; elements would have the following behaviour:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a &lt;code&gt;tab&lt;/code&gt; element with &lt;code&gt;for&lt;/code&gt; attribute that matches the &lt;code&gt;id&lt;/code&gt; attribute of &lt;code&gt;content&lt;/code&gt; element is in &lt;code&gt;"active"&lt;/code&gt; state. The &lt;code&gt;content&lt;/code&gt; is painted.&lt;/li&gt;
&lt;li&gt;Activating a different &lt;code&gt;tab&lt;/code&gt; in the same &lt;code&gt;nav&lt;/code&gt; as the one that currently controls the &lt;code&gt;content&lt;/code&gt; hides the element.&lt;/li&gt;
&lt;li&gt;Newly activated &lt;code&gt;content&lt;/code&gt;s gain focus, the same way &lt;code&gt;dialog&lt;/code&gt; elements do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My point is, HTML native tabs don't (yet) exist. One might want to create a visual primitive for tabs. The way to do that is to replicate the native-like behaviour, some of which I've listed above. We don't want to have to do this every time we want to create a visual primitive for tabs. This is where headless UI libraries come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless UI
&lt;/h2&gt;

&lt;p&gt;Headless UI libraries are libraries that provide the bare logic behind a certain component. That component can be very complex, like a data table (e.g.: &lt;a class="mentioned-user" href="https://dev.to/tannerlinsley"&gt;@tannerlinsley&lt;/a&gt;'s TanStack Table) or simple, such as a button, with things like &lt;code&gt;aria-disabled&lt;/code&gt; attribute applied based on whether a &lt;code&gt;disabled&lt;/code&gt; prop is passed in, because it &lt;a href="https://css-tricks.com/making-disabled-buttons-more-inclusive/#aa-the-difference-between-disabled-and-aria-disabled" rel="noopener noreferrer"&gt;gives a more inclusive user experience&lt;/a&gt;, compared to &lt;code&gt;disabled&lt;/code&gt; attribute. Some headless UI libraries are framework specific, like those made specifically for React or Vue and some are based on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components" rel="noopener noreferrer"&gt;Web Components&lt;/a&gt; and work across different frameworks.&lt;/p&gt;

&lt;p&gt;Decoupling styling from behaviour has advantages and disadvantages. I think the pros far outweigh the cons, but I'll let you decide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Increased setup time&lt;/li&gt;
&lt;li&gt;Paradigm shift requires education&lt;/li&gt;
&lt;li&gt;Potentially more lines of code overall&lt;/li&gt;
&lt;li&gt;If the logic and the styles are kept separate, maintainers need to perform the following activities for both:

&lt;ul&gt;
&lt;li&gt;Onboarding&lt;/li&gt;
&lt;li&gt;Versioning&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hyper-focused codebase. This allows developers to truly isolate a certain aspect of development, e.g.: logic, performance or visuals and focus on that aspect in isolation&lt;/li&gt;
&lt;li&gt;Polyglot UIs. Separating visuals from logic allows maintainers to simply extend the library to be used with many frameworks. For example: my current company uses Vue and React. We built our UI library with React, but we could take the headless UI library we used, called Radix, install its Vue counterpart and plug in our styles. We'd get identical behaviour and looks, but a truly polyglot system.&lt;/li&gt;
&lt;li&gt;This method introduces certain limitations. Why is this a pro? These limitations make it more straightforward to keep in line with good engineering practices that enable your team to build your library on solid principles. Some of these practices:

&lt;ul&gt;
&lt;li&gt;Relying on the browser for as many things as possible&lt;/li&gt;
&lt;li&gt;Relying on CSS for as many things as possible - this is often overlooked. CSS is almost always more performant than the JavaScript counterpart, for things like animations. It is more maintainable as it's more limited.&lt;/li&gt;
&lt;li&gt;Keeping JavaScript logic simple, small and contained&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;More scalable codebase, because each module is limited to a very small subset of features, adding to it is almost always linear.&lt;/li&gt;

&lt;li&gt;The chance of a change affecting something unexpectedly is minimal.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;I'm sold, what does the architecture look like?&lt;/p&gt;

&lt;p&gt;Take a Button for example. We'll have modules to begin with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Headless button - this could simply be a HTML button element.&lt;/li&gt;
&lt;li&gt;Button styles - this is the "head" to the headless button. It provides raw styles according to our design guidelines.&lt;/li&gt;
&lt;li&gt;Visual Primitive - this will be a framework specific combination of the headless button and the styles.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdusye4bt39xa2midjc2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdusye4bt39xa2midjc2d.png" alt="Headless button box, underneath a Button styles box, arrows pointing from both into a third box: Button primitive" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Implementing a React and Vue version of the library would yield the following project structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvrap63imjk0upuoxq9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvrap63imjk0upuoxq9n.png" alt="Vue headless UI combined with common styles makes a Vue component library, React headless ui combined with the same styles creates a React component library" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools and Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Styling
&lt;/h3&gt;

&lt;p&gt;I've used countless styling solutions, from CSS &amp;amp; BEM, through CSS Modules, CSS-in-JS - both runtime and statically extracted, inline styles, utility frameworks and everything in-between. When picking a styling solution, you want it to compile fast, produce performant CSS and improve developer experience.&lt;/p&gt;

&lt;p&gt;To me CSS-in-JS doesn't tick all of those boxes. More concretely put, it has too many foot-guns, when it comes to performance. Unless you know how to work around limitations, you can end up creating an application that has some serious performance bottlenecks. Most CSS-in-JS solutions also require you to define styles separately and then use them in some way. This means you have to worry about naming - the most difficult thing in programming.&lt;/p&gt;

&lt;p&gt;Using plain ol' CSS is fine. In 2023 and beyond I wouldn't use any pre-processors, like SASS and SCSS. Modern CSS is more than capable of covering the majority of use-cases. Using a pre-processor limits you to a set of features implemented by that tool. When these tools go out of fashion and become unmaintained, you'll end up with bugs unfixed and CSS-native features missing. I do, however, recommend post-processing. Ironing out differences between browsers and applying a CSS normaliser or reset will give you a nice base to work off of.&lt;/p&gt;

&lt;p&gt;I've had the best results using CSS utility frameworks, like &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt;. The idea is to turn each atomic style into its own rule and apply it via classname. Tailwind isn't the only option, but it's the most popular one today. A cool alternative we use at my current company is &lt;a href="https://unocss.dev/" rel="noopener noreferrer"&gt;UnoCSS&lt;/a&gt;. Other notable examples include GitHub's Primer Design System that also comes with a utility framework that's similar to Tailwind. These tools are opinionated, easy to use and set up, quite simple to onboard people into and allow you to move fast.&lt;/p&gt;

&lt;p&gt;Another advantage of using utility frameworks like Tailwind, that isn't as talked about yet, is that they play very well with LLM-based code generation tools, like GitHub Copilot. Both the elements and the styles are in the same place, so it's possible to generate parts of UI in one go. It also makes it easier for the AI tools to pick up on the general style and layout of your project. We've gotten the best AI generation results so far by using utility frameworks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Headless UI Libraries
&lt;/h3&gt;

&lt;p&gt;When choosing a headless UI library it's best to take all available popular options out for a spin and see which one works closest to your project's needs. We didn't consider the API of the library, because we knew we'd be able to adapt any library to our needs, using transformations or a compat-layer depending on which one makes sense. Most headless UI libraries come packaged individually per component, which means it's also possible to mix and match. Switching over from one to another can also be done incrementally due to this. We currently use a mixture of &lt;a href="https://headlessui.com/" rel="noopener noreferrer"&gt;Headless UI by TailwindLabs&lt;/a&gt;, &lt;a href="https://www.radix-ui.com/" rel="noopener noreferrer"&gt;Radix UI&lt;/a&gt; and &lt;a href="https://tanstack.com/table/v8" rel="noopener noreferrer"&gt;TanStack Table&lt;/a&gt; for data tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development and Building
&lt;/h3&gt;

&lt;p&gt;About a year ago, we've made the commitment to switch over to Vite from Webpack. This gave us improved bundling times and better development experience. Fast refresh blows hot reload out of the water and the plugin system is much more straightforward to work with. In fact I've even ended up creating a custom plugin for our products to enable module federation for our React frontends, and it was a downright pleasant experience, compared to writing Webpack plugins. Bundling applications is just as simple to do with Vite. Using the same tool to build our apps and libraries gives the added benefit of being able to apply the same level of optimisation out of the box on both ends. This leaves us with no unnecessary polyfills or wrong build targets. We can also use the same set of plugins for both, which means we could even expose the UI library as a microfrontend via module federation at some point if we wanted to.&lt;/p&gt;

&lt;p&gt;For testing, we're using &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt;, another gem by AntFu. It works with our Vite config directly, so whatever code our tests are running will be the same code our users will be getting in their browsers. This is very important and a huge step up compared to using a Jest based setup that I often relied on in the past. Gone are the days of "why does it work in my browser and not my tests?" and vica versa. Our development environment is powered by &lt;a href="https://ladle.dev/" rel="noopener noreferrer"&gt;Ladle&lt;/a&gt;, which is a Storybook alternative, based on Vite (you might notice a pattern here). Using the same build tool to run everything end to end means that we've so far reported 0 issues, caused by the misalignment between different environments. The final piece of the puzzle is integration testing. One of the most important aspects of maintaining a UI library is visual integrity. Introducing unwanted visual and behavioural changes can break trust in a product. Using &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;PlayWright&lt;/a&gt; and our Ladle stories, we can set up a suite of tests to compare behaviour changes between branches. We can also take screenshots which PlayWright saves inside the project. This is quite cool, because intended differences are expressed via git commits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping It Up: The UI Library Odyssey
&lt;/h2&gt;

&lt;p&gt;So, there you have it — a whirlwind tour through the quirky and sometimes bewildering world of UI libraries. From battling the behemoths of bundle sizes to choreographing the delicate dance of accessibility and interactivity, it's been quite the journey. We've navigated the seas of visual primitives, tiptoed through the complexities of headless UI, and even dipped our toes into the ever-changing currents of development tools.&lt;/p&gt;

&lt;p&gt;What's the takeaway from this techy tale? Whether you're streamlining a sprawling video platform or jazzing up a sports betting interface, the right UI library isn't just a tool; it's a trusty sidekick in your quest for customer and developer satisfaction.&lt;/p&gt;

&lt;p&gt;Remember, in the ever-evolving landscape of web development, the only constant is change. So, keep your wits sharp, your code cleaner, and your UI snappier. Until next time, happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ui</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Taking Go Generics for a Spin</title>
      <dc:creator>Daniel Emod Kovacs</dc:creator>
      <pubDate>Thu, 01 Sep 2022 11:26:04 +0000</pubDate>
      <link>https://dev.to/danielkov/taking-go-generics-for-a-spin-29l4</link>
      <guid>https://dev.to/danielkov/taking-go-generics-for-a-spin-29l4</guid>
      <description>&lt;p&gt;Generics are a part of most major programming language as a way to use types as parameters to function, classes, structures and so on. Historically, GoLang had been known for being a popular and newer programming language, without the added complexity of generics, which was commonly regarded as a bonus in some circles. Nevertheless, this all changed as &lt;code&gt;1.18&lt;/code&gt; rolled out with a shiny new feature: generics. They're so new that even the standard libraries aren't fully migrated to generics yet. I thought I'd take generics out for a spin and tackle a problem I've not yet seen addressed: loading environment variables and processing them to their desired types in an eloquent way. Disclaimer: this was my first experiment with generics in Go, so take it with a grain of salt. Here goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Syntax
&lt;/h2&gt;

&lt;p&gt;First of all, languages like Java have generic type arguments in their DNA, so much so that mostly anything can be extended with generic type arguments, however in Go, the approach is somewhat different. The first limitation is that generics can not be used on methods, only functions. Some might see this as a non-issue, given that methods are just syntactic sugar for defining the same function with the "instance" as the first argument and then calling it directly with the instance passed in as a parameter. A bit more verbose, but gets the job done. We won't be doing that today, though. You can add generic type parameters to functions and make types generic. This system isa bit limited, but it's actually perfectly in line with the philosophy of Go: the less stuff you can do, the fewer the ways you can invent to solve problems and thus your code will be closer to everyone else's. In today's post I'm exploring adding generic type arguments to functions.&lt;/p&gt;

&lt;p&gt;To do so, I can use the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// here I pass in T as a generic argument&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;At&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Couple of things to note. Whenever you pass in a type parameter, you must also define what it conforms to. To make it a bit easier, the GoLang team mapped our favourite type &lt;code&gt;interface{}&lt;/code&gt; to the keyword &lt;code&gt;any&lt;/code&gt;, which will conform to anything you give it. You can use this mechanism to make sure the passed in argument conforms to a certain interface, such as &lt;code&gt;comparable&lt;/code&gt; if you want to sort, order or filter things.&lt;/p&gt;

&lt;p&gt;You can also define the type of inputs and pass them into generic types or turn them into slices.&lt;/p&gt;

&lt;p&gt;The function can take regular parameters too, but honestly, what would be the point if it couldn't.&lt;/p&gt;

&lt;p&gt;You can also tell the function that the return type has something to do with the generic argument too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy Env
&lt;/h2&gt;

&lt;p&gt;My library will be called &lt;code&gt;lazyenv&lt;/code&gt;. It's a small library with a single purpose: allowing the user to get environment variables in a lazy way - caching those on the first instance of retrieving the variable and also converting them to the desired type in an eloquent way.&lt;/p&gt;

&lt;p&gt;Let's look at an example of what I'm trying to achieve. Say we have an environment variable as &lt;code&gt;BUSLINES=7,8,108,133,907,908,932,956,973,990&lt;/code&gt; and in my program I want to have a list of these bus lines. Now I know that all buses have a positive number between 0-999, which means we can use an unsigned integer. 8 bits will not cover our full range, but 16 bits will. In pseudo code, I want my library's interface to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;buslines = get "BUSLINES" as uint16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Designing an Interface
&lt;/h3&gt;

&lt;p&gt;As I've mentioned before I want to design an eloquent interface for users to interact with my library. An eloquent interface is one that reads as close to human language as possible, but without abstracting function and variable names too much that in the process they become completely disconnected from their actual purpose. Let's see an example of an eloquent interface for Go, based on the above design.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;buslines&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lazyenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BUSLINES"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Uint16Slice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To implement something like this, we'd do the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;lazyenv&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;
    &lt;span class="s"&gt;"strings"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Uint16Slice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vals&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint16&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;vals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseUint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;buslines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BUS_LINES"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Uint16Slice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But wait, where are the generics?&lt;/p&gt;

&lt;p&gt;Don't worry, we'll get to that soon. A small hint: we might not end up using this API.&lt;/p&gt;

&lt;p&gt;Next thing I want to add is the ability to define a default value that should be returned, if the environment variable is empty.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Builder Pattern
&lt;/h3&gt;

&lt;p&gt;The pattern we're using here is based on the builder pattern. In the builder pattern we use a base object, class or struct to accumulate the information we're building. We're using methods on the instance of the builder to "build" values. When we're done building, we finalise the result by calling a designated method or in some cases, multiple methods can yield a result, like in my example, where we could finalise the builder to a &lt;code&gt;.String()&lt;/code&gt;, &lt;code&gt;.Uint16Slice()&lt;/code&gt; or &lt;code&gt;.Interface()&lt;/code&gt; among others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;defaultValue&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;defaultValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add some generics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;defaultValue&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The env struct now supports a generic argument. This will light up our code like a Christmas tree. We need to supply this generic argument everywhere to satisfy the compiler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;defaultValue&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our builders methods now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;defaultValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;Uint16Slice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vals&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint16&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;vals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseUint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler can technically infer this argument, however in this specific situation it isn't possible because we're moving backwards. We're only instructing with actual values what the type should be once the struct is already built.&lt;/p&gt;

&lt;p&gt;What we do get, however is type safety. We can't supply a wrong default value, because our program won't compile.&lt;/p&gt;

&lt;p&gt;Here's what our code to get this variable becomes now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;buslines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;[[]&lt;/span&gt;&lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="s"&gt;"BUS_LINES"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Uint16Slice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's weird about this code now, is that we have to declare our type twice.&lt;/p&gt;

&lt;p&gt;Another problem is the logic to make default values work will now present us with a little problem.&lt;/p&gt;

&lt;p&gt;There is actually nothing stopping you from providing a &lt;code&gt;[]uint16&lt;/code&gt; as the default value but asking for a &lt;code&gt;.String()&lt;/code&gt; to be returned. Our default value and struct are already typed at this point, but sadly there's no way for us to grab an initialiser for that type, because type information isn't dynamic at runtime, it is - again, just syntactic sugar, that let's you write a function with the same signature once, but in reality will work the same way as though you typed that function in place. In other words, the following just isn't possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;AccessType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"uint16"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will bring us to the problem at hand:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybz1kty60b3ug68g7qs2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybz1kty60b3ug68g7qs2.png" alt="VSCode shows an error which reads: cannot use e.defaultValue (variable of type T constrained by any) as []uint16 value in return statement" width="800" height="143"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My other gripe with this whole approach is extensibility. In Swift, it is possible to extend any interface and it will all just magically end up being wired together. Swift is a much more complex language, however, and Go does not allow you to do such a thing, so using a builder pattern will mean that ultimately this library will ultimately be limited by the mappings I add to it as finaliser methods. One can't come in and provide third-party mappings to different types.&lt;/p&gt;

&lt;p&gt;At this point, I know I'll need more generic functions or methods, but I also want to pass in the type at the earliest possible time. Let's drop the builder pattern for now and use function composition instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function Composition
&lt;/h3&gt;

&lt;p&gt;With the function composition pattern, we provide a single point of entry, much like with the builder pattern, however we define additional behaviour by introducing functions as parameters. Here, I'll need a mapper and a default value getter function. I elected to use a function to return the default value rather than just passing it in for 2 reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This makes it more lazy - meaning that if we don't end up needing a default value, the program won't have to initialise it. The tradeoff is that if our default value was just a primitive value or something simple and not resource intensive, then we'd end up with more overhead, however if, for example, we want to fetch the values from an API if the environment doesn't provide them, we can do that in an eloquent way, without sacrificing performance.&lt;/li&gt;
&lt;li&gt;This allows for function composition to control the behaviour of the fallback logic. E.g.: this lets us make it so that no default value is returned, but the program returns an error instead or we can even panic right away.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So why not just use parameters to fine-tune behaviour?&lt;/p&gt;

&lt;p&gt;If you're already sold on function composition, feel free to skip this paragraph, but for those of your skeptics out there, I present:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// a simple interface&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's use parameters to define the behaviour of this function. Should we return the error if no value? Should we just not do anything? Should we panic?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;returnError&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;panicOnMissing&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where does the default value go?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;returnError&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;panicOnMissing&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defaultValue&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now our invocation looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our implementation is arguably also a mess and there is no constraint stopping us from passing in &lt;code&gt;true&lt;/code&gt; for both behaviours and also adding a default value, in which case, which one takes precedence?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;returnError&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;panicOnMissing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"returnError and panicOnMissing cannot both be true"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;returnError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;panicOnMissing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you look at the above line, do you know what each parameter does? Even I don't remember and I wrote it not a minute ago. So what would this look like with function composition?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onMissing&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a stab at implementing panic on missing value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;OrPanic&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s is not set"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use it, one can pass it into our getter, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EXAMPLE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrPanic&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note, we instantiate &lt;code&gt;OrPanic&lt;/code&gt; here with the &lt;code&gt;string&lt;/code&gt; type, which also allows &lt;code&gt;Get&lt;/code&gt; to infer the type or &lt;code&gt;T&lt;/code&gt; to be. This is mandatory, otherwise Go wouldn't know what type it has to apply during build.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's take this a step further and implement returning an error if our value is missing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;OrError&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to get %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can only use one or the other, so that takes care of transparently deterministic behaviour:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EXAMPLE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrError&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can provide a default value, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;OrReturn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;defaultValue&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice, how we're using a factory to create a function that matches the signature that we need for the parameter that we pass to &lt;code&gt;Get&lt;/code&gt;. Here's what the usage looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BUSLINES"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrReturn&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;{}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One great thing to note here, is that because we're actually passing in a parameter here that we annotated with the generic type argument &lt;code&gt;T&lt;/code&gt;, we do not have to also instantiate the type parameter, because of inference.&lt;/p&gt;

&lt;p&gt;Let's map these originally &lt;code&gt;string&lt;/code&gt; values to something more useful. Let's try an &lt;code&gt;int&lt;/code&gt; first. Those of you familiar with the &lt;code&gt;strconv&lt;/code&gt; library will notice that it actually comes with a function that we can already use as is, because it matches our signature of the mapper. I'll let you take a guess what it is. Leave a comment down below if you got it correct!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Mapper&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;Get&lt;/code&gt; function now becomes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getDefaultValue&lt;/span&gt; &lt;span class="n"&gt;GetDefaultValue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt; &lt;span class="n"&gt;Mapper&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use it as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"EXAMPLE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;strconv.Atoi&lt;/code&gt; also adheres to this interface, so it's possible to map to an &lt;code&gt;int&lt;/code&gt; right away:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"NUMBER"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we can make it more fluent and just keep a function at hand for this specific task too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to find a way to get our slice of numbers in our list separated by &lt;code&gt;,&lt;/code&gt;. We'll take advantage of composition and generic arguments yet again, to achieve such feat.&lt;/p&gt;

&lt;p&gt;I'm going to design a function, that takes a &lt;code&gt;Mapper&lt;/code&gt; as an argument and returns a slice of the type of whatever the &lt;code&gt;Mapper&lt;/code&gt; maps to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;SliceOf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;mapper&lt;/span&gt; &lt;span class="n"&gt;Mapper&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;Mapper&lt;/span&gt;&lt;span class="p"&gt;[[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can then take this function and pass it into my &lt;code&gt;Get&lt;/code&gt; to maintain the eloquence (is that even a word?) of this library, while adding new functionality. Keep in mind, I'm now just adding on top of my already existing "platform", which is the extensible API I've designed earlier. One could theoretically implement any mapper or mapper factory based on their specific needs.&lt;/p&gt;

&lt;p&gt;The final example for my use case is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;buslines&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BUSLINES"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Required&lt;/span&gt;&lt;span class="p"&gt;[[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;SliceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ambiguity
&lt;/h3&gt;

&lt;p&gt;We have one more issue we need to fix before we can move on to implementing this library. Currently our &lt;code&gt;GetDefaultValue&lt;/code&gt; and &lt;code&gt;Mapper&lt;/code&gt; types are in fact the same. This means that Go will let you pass in a &lt;code&gt;Mapper&lt;/code&gt; for &lt;code&gt;GetDefaultValue&lt;/code&gt; and vica versa. A language feature that would resolve this problem is lexical type assertion, where one can define a given variable, or function as a certain type and that is enforced via the type system, even if the two types in question conform to each other. Go's type system is extremely flexible and as such the mechanism I described doesn't exist within it. Instead we can just change the signatures of the function, which is slightly inconvenient, however it will let us differentiate between the two different types of functions we export and use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GetDefaultValueParams&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GetDefaultValue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="n"&gt;GetDefaultValueParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Aside about tests
&lt;/h3&gt;

&lt;p&gt;I've made this change after finishing the implementation itself and with 100% test coverage. After updating the implementation to match the new logic, I didn't have to touch any of my tests and they still passed, which is a sign of a robust test suite - it lets you refactor freely, as long as you retain all of the original functionality.&lt;/p&gt;

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

&lt;p&gt;I am personally a huge fan of generics. The generic system in Go is a controversial one, because it does remove from the simplicity of the language that it was designed for. It also isn't as flexible and "smart" as other ones. Java's generics system is more robust, while the one in TypeScript is a lot more proactive with inference, which leaves you typing less code. The long-term effect of having generics as part of the language is going to be a positive one, especially as soon as the standard library gets reworked to make use of generics.&lt;/p&gt;

&lt;p&gt;If you want to see the implementation of this library or just want to use it in your project, I've put &lt;a href="https://github.com/danielkov/lazyenv" rel="noopener noreferrer"&gt;all of the source code on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>tutorial</category>
      <category>testing</category>
    </item>
    <item>
      <title>7 Tips to Crush Your Next System Design Interview</title>
      <dc:creator>Daniel Emod Kovacs</dc:creator>
      <pubDate>Fri, 17 Dec 2021 11:46:41 +0000</pubDate>
      <link>https://dev.to/superbet/7-tips-to-crush-your-next-system-design-interview-4cfe</link>
      <guid>https://dev.to/superbet/7-tips-to-crush-your-next-system-design-interview-4cfe</guid>
      <description>&lt;p&gt;It is no secret that the tech industry is blooming right now. Many big tech companies are expanding at a mind-boggling pace, which of course means a rapid influx of applicants. This leads to a need for optimising and streamlining the interview experience.&lt;/p&gt;

&lt;p&gt;We at &lt;a href="https://superbet.engineering" rel="noopener noreferrer"&gt;Superbet&lt;/a&gt; invest a lot into making our interviews concise, comprehensive and reproducible, to ensure all applicants get a fair and equal chance.&lt;/p&gt;

&lt;p&gt;One of the essential parts of our interview process is the &lt;strong&gt;System Design Interview&lt;/strong&gt;. It is not something we invented, but I think we're pretty good at giving candidates fair, yet challenging problems to think about for this ~1 hour section of our hiring flow. In my first 6 months of working at Superbet as a tech lead, I've conducted more than 20 interviews - the majority of which had been focusing on system design. With that experience in my bag, I'll spoil you with the best 7 pieces of advice I could come up with to help you ace your next system design interview.&lt;/p&gt;

&lt;p&gt;During a system design interview you're presented with a technical problem, e.g.: "how would you design an application, like DEV.to?" and your task is to talk the interviewers through your solution while covering a couple of different topic, e.g.: data modelling, services, scaling, frontend, logging and error handling, just to name a few.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understand the Problem
&lt;/h2&gt;

&lt;p&gt;This may sound cliché, but understanding the problem you're presented is going to give you a great advantage. So many candidates rush into trying to pump out a solution as quickly as they humanly can, without taking the time to really try to understand the question or problem in the first place.&lt;/p&gt;

&lt;p&gt;Let's examine why system design interviews exist and what we're trying to measure. Contrary to popular belief, after the interview concludes, we don't actually take the plan you've given us and turn it into the next unicorn startup. We're actually okay with you not giving us a full solution. What we're looking for is the way you approach a technical problem and how well you can reason about your decision making.&lt;/p&gt;

&lt;p&gt;The skills you will showcase during the system design interview will be able to tell us how well you'll manage problems in all sort of areas of engineering and not just in the specific environment that's presented during the interview.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Collect all of the Requirements
&lt;/h2&gt;

&lt;p&gt;A big mistake a lot of good engineers make, when tackling a system design interview is the lack of questions about the problem. We can't really score you on the assumptions you've made during the interview, although they do give us good insight into how your mind works. It's always safer to just take your time and ask all of the questions that come to your mind.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I like to say this phrase when introducing the system design interview to candidates who hadn't had a chance to take part in one yet: "your questions are just as valuable as your answers".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A good rule of thumb is, if you're about to answer a question starting with "it depends", instead, explain that you need further clarification of specific parameters of the problem that will help you inform your decision. For example, don't just assume you can use AWS for everything. Certain countries may have regulations that prohibit businesses in a couple of different sectors from relying on cloud infrastructure and therefore you'd need to take into consideration the use of on-premise solutions if this is the case.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Focus on Note Taking
&lt;/h2&gt;

&lt;p&gt;I know I have a horrible short term memory. To help with remembering details I take notes throughout the day and review them regularly. You don't have to have a bad memory to take advantage of note taking. It will not only benefit you in an extremely stressful situation, by taking reliance on your memory out of the equation, but it also helps interviewers by showcasing what information you're focusing on.&lt;/p&gt;

&lt;p&gt;Sometimes a system design interview will present you with a complex problem, especially as you climb higher on the engineering ladder. It's okay to lose track during the interview, however, the way you handle the situation or prevent it from happening in the first place is what's really important to us.&lt;/p&gt;

&lt;p&gt;If you're sharing your screen during the interview or are doing the interview in person, you will have a way of showing your notes to your interviewers. I recommend making sure they're aware that you're taking notes and ask if they're interested in your notes. Chances are they will be.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Use a Visualisation Tool
&lt;/h2&gt;

&lt;p&gt;The result of the system design interview is a snapshot of a working system with explanation of the choices you've made while coming up with the design. One of the biggest challenges for both the interviewers and the candidates is to keep track of the final solution. We always recommend our candidates to use a visualisation tool that can not only help them with an overview of what they have so far, but also to help us see the solution at a bird's eye view.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The tool I recommend using is &lt;a href="https://app.diagrams.net/" rel="noopener noreferrer"&gt;Draw.io&lt;/a&gt;. The disadvantage of it is that there's no live sharing feature, so the only way for us to see your solution is for you to share your screen. &lt;a href="https://docs.google.com" rel="noopener noreferrer"&gt;Google Docs&lt;/a&gt; is also a viable alternative, albeit with limited options when it comes to drawing shapes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. Do Not Get Lost in the Details
&lt;/h2&gt;

&lt;p&gt;Your solution should be comprehensive and should cover a wide array of topics of software design. It's also important to discuss edge cases and non-critical system components, e.g.: logging. The number one reason candidates fail to deliver a full solution to the system design interview on time is lack of focus on higher level issues, a.k.a.: getting lost in details.&lt;/p&gt;

&lt;p&gt;To make sure you don't lose yourself in the little details of your solution, I recommend the following approach. Instead of picking the area you're most familiar with, and expanding on it horizontally - you should start at the highest possible level. Explain what you expect your application to be able to do and then work your way down into the specifics of each component of the system.&lt;/p&gt;

&lt;p&gt;As an interviewer, I want to intervene as little as possible during the interview. I want to keep the candidate talking, without having to guide them. When you get lost in the details, your interviewer has to make a decision to intervene and interrupt the flow or let you talk, but risk you wasting precious time in details that are not required in your solution. The best way to make sure you provide enough detail is to ask before you give your solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Talk Through Your Process
&lt;/h2&gt;

&lt;p&gt;From my experience, the most successful candidates all have one quality in common. They are vocal. You might be someone who finds it easy to talk through your thinking process, however that isn't true for everybody and I appreciate that. It's something not everyone's good at naturally, however I recommend practicing thinking out loud, while you're preparing for an interview and you'll find it easier to do during your system design interview as well.&lt;/p&gt;

&lt;p&gt;Why is this important at all? To be an effective engineer, your communication skills are extremely important. For more junior engineers we want to make sure that you'll be able to ask your more senior teammates for advice when working on your tasks, while as a senior, we're looking for you to be able to jump in and mentor your teammates, as well as take part in discussions about tech.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Do Not Be Afraid to Ask for Help
&lt;/h2&gt;

&lt;p&gt;When you're doing your system design interview at Superbet, we'll try to create the atmosphere of a nice open-ended discussion between tech enthusiasts. As such, we'll be open to answering any and all of the questions you may come up with during the interview.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have you ever wanted to say during an interview: "I'd just Google x and y"?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On a system design interview it's okay not to know the exact technology or library that you'd use for a solution. In the real world you will be able to get help with all of that, whether it be reading documentation or looking the problem up on StackOverflow.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I'd use Redis, because I don't have to worry about persistence or memory use, but I need very quick reads and a way to publish changes as they happen"&lt;/em&gt; scores just as well as &lt;em&gt;"I'd use an in-memory database, because I don't have to worry about memory and they have quicker access speeds. If it's got built in pub/sub, it's even better. Can you suggest such a database?"&lt;/em&gt;. Remember, we're interested in your reasoning above all and if the actual answer is just a Google search away, we'll be happy to help you out with it.&lt;/p&gt;




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

&lt;p&gt;If you haven't been in a system design interview or are looking to improve the outcome of your next one, hopefully my tips will get you there. Remember, your mileage may vary. Not everybody does interviews the same way, so if you want to be safe, you can use all of the above in your interview at Superbet. You can find a link to our open positions page on &lt;a href="https://superbet.engineering" rel="noopener noreferrer"&gt;our engineering website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>systems</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>career</category>
    </item>
    <item>
      <title>WordPress REST API as a Back-end with React and Docker (Part 2)</title>
      <dc:creator>Daniel Emod Kovacs</dc:creator>
      <pubDate>Tue, 30 Nov 2021 17:52:58 +0000</pubDate>
      <link>https://dev.to/danielkov/wordpress-rest-api-as-a-back-end-with-react-and-docker-part-2-1lbe</link>
      <guid>https://dev.to/danielkov/wordpress-rest-api-as-a-back-end-with-react-and-docker-part-2-1lbe</guid>
      <description>&lt;p&gt;In &lt;a href="//./wordpress-rest-api-as-a-backend-with-react-and-docker-part-1"&gt;part 1 of this series&lt;/a&gt; I taught you how to get up and running with WordPress and Docker. In this one we'll see how we can integrate React with WordPress' RESTful API to be used as a back-end solution for our CRUD project. Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the ⚛️ React App
&lt;/h2&gt;

&lt;p&gt;To create a new React single-page application, let's use &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;&lt;code&gt;create-react-app&lt;/code&gt;&lt;/a&gt;, which is what's recommended in the official docs and is an opinionated, batteries included tool to quickly scaffold React applications. You can add it globally with the usual &lt;code&gt;yarn global add create-react-app&lt;/code&gt; or &lt;code&gt;npm install -G create-react-app&lt;/code&gt;, but I don't want it to stay on my computer since I will only use the command once per project, so I'll use &lt;a href="https://github.com/zkat/npx" rel="noopener noreferrer"&gt;&lt;code&gt;npx&lt;/code&gt;&lt;/a&gt; to execute the binary from a temporary location and then remove it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-react-app wordpress-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we set up our project, we'll &lt;code&gt;cd wordpress-react&lt;/code&gt; and use &lt;code&gt;yarn start&lt;/code&gt; to get the live development server with Webpack rolling. I do not mean for this to be an introduction to React. The documentation and the countless tutorials available online will be more than enough to get you started. I'll show how to integrate the WP REST API with &lt;code&gt;react-router&lt;/code&gt; and I'll take this chance to make use of the new Context API of &lt;strong&gt;React 16.3+&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's add dependencies and get working on the app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add react-router react-router-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;The first thing I always do to get my head around to working with a new project is setting up the directory structure. For this project we'll use the new Context API for state management and React Router v4 for routing, so knowing that we'll come up with the following structure to support our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;- src
  | - components
  | - containers
  | &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Store.js
  | &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; App.js
  | &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll use two types of components: presentational components, which will have all the styles and container components, which will handle interaction with Context via lifecycle methods and will pass those down to presentational components.&lt;/p&gt;

&lt;p&gt;Let's clear up our &lt;code&gt;App.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, WordPress!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll revisit this one later when we add store and routes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extending Development Environment
&lt;/h2&gt;

&lt;p&gt;Next up we'll add the final service to our &lt;code&gt;docker-compose.yml&lt;/code&gt;, which will tell Docker to add our front-end to the network. The &lt;code&gt;npm run start&lt;/code&gt; process will run inside a Docker container, but we'll mount our source directory as a volume, which will mean that any change we make during development will trigger the watcher inside the container and will reload the app just as if it were running on the host machine.&lt;/p&gt;

&lt;p&gt;As of now, I am keeping everything inside the root project directory, that &lt;code&gt;create-react-app&lt;/code&gt; created for us. Let's add this new service to the &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3000:3000'&lt;/span&gt;
  &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.:/app'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may notice the line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells compose to look for a &lt;code&gt;Dockerfile&lt;/code&gt; in the same directory, which we do not yet have. Let's fix that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:alpine&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /app
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./package.json /app/package.json&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; [ "npm", "start" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll copy our &lt;code&gt;package.json&lt;/code&gt; for NPM to be able to install our dependencies, before the mounting happens. This will mean that whenever we restart the container, it will not have to pull dependencies every time. One more thing we need to add in order for the React App to reach the WordPress instance is the &lt;code&gt;proxy&lt;/code&gt; config field in the &lt;code&gt;package.json&lt;/code&gt; file, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"proxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://wordpress"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see what will happen inside and outside the Docker network:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4wcab27w3bba6uemnl2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4wcab27w3bba6uemnl2r.png" title="WordPress Diagram" alt="Diagram of the data flow in network" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can still access the WordPress service too, via visiting &lt;code&gt;http://localhost&lt;/code&gt; on our computers, however that is not how it can be accessed inside the network, which is the reason why we added it to a proxy config. This means that requests that should not be served with a valid URL within our application will be redirected to go to the WordPress service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Store
&lt;/h2&gt;

&lt;p&gt;React 16.3 brought about a new Context API, which is more intuitive and in this guide it will replace Redux, which is what I initially wanted to use before the new stuff came out. The way the new API works is you have &lt;code&gt;Provider&lt;/code&gt; and &lt;code&gt;Consumer&lt;/code&gt; tied to each context you create. To get these two, you can fire off a call to the new &lt;code&gt;createContext&lt;/code&gt;, which accepts a parameter, which will be the default value that can be accessed inside the context. Using context is still a way to bypass intermediate components, when passing data deep down within components, however the new API is way more intuitive and is actually easier to set up than Redux, so let's see how it is done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Consumer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could just wrap the whole application insde the &lt;code&gt;&amp;lt;Provider/&amp;gt;&lt;/code&gt;, however we also want to be able to retrieve data, which will manipulate context. For this we'll create a wrapper component, which uses the Provider and can pass down data as well as methods for data retrieval, much like &lt;code&gt;mapDispatchToProps&lt;/code&gt; in &lt;code&gt;redux&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can test out how the &lt;code&gt;&amp;lt;Consumer/&amp;gt;&lt;/code&gt; works by just initializing the state with some sample data and creating the presentational components. Inside the &lt;code&gt;containers&lt;/code&gt; directory we'll create components that make use of the &lt;code&gt;Consumer&lt;/code&gt;'s &lt;code&gt;children&lt;/code&gt; prop, which is a function that recieves whatever is the current &lt;code&gt;value&lt;/code&gt; of the &lt;code&gt;Provider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's add this container component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// containers/PostsContainer.js&lt;/span&gt;
&lt;span class="c1"&gt;// ... imports&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PostsContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PostsView&lt;/span&gt; &lt;span class="na"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;PostsContainer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to create this component which will interact with the consumer via props. Now theoretically we could just create this in the same file, since we should not use this separately, however for testability, this approach is better.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/PostsView.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsView&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;excerpt&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rendered&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;PostsView&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point we do not have any data coming in, so before we add actual server-side data, we'll just add the following dummy data to initialize the Store with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store.js&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, HardCoded Data!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2018-04-17T00:17:18.040Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello-world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rendered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some random text from the excerpt.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The post object is the exact structure that is returned by the WordPress REST API. Finally let's add the container component and the store to the application itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;
&lt;span class="c1"&gt;// ... imports&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PostsContainer&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look at how to actually retrieve data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store.js&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Store&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="nx"&gt;loadPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/wp-json/wp/v2/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;loadPosts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we added a new method called &lt;code&gt;loadPosts&lt;/code&gt;, which makes a network call and upon recieving data, it will set the state to the new data, which in turn will also update each &lt;code&gt;Consumer&lt;/code&gt;. We also need to add the new method to the provider's values. This is what we'd do when we provide the &lt;code&gt;mapDispatchToProps&lt;/code&gt; parameter of &lt;code&gt;redux-connect&lt;/code&gt;. The final thing we have to do is make use of it in the &lt;code&gt;PostsView&lt;/code&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/PostsView.js&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsView&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;componentDidMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is way simpler than doing it with thunks or &lt;code&gt;redux-saga&lt;/code&gt;, however we are still coupling all our logic in a single component, which is better than having it in the state of each individual component, but may get clunky with large applications.&lt;/p&gt;

&lt;p&gt;In the next and final post of this series we'll see how we can integrate React Router with this application as well as adding a method to retrieve a single post. If you are already familiar with React Router, you'll know how to go on about creating the rest of the site using WordPress and React. Otherwise, be on the lookout for the next post.&lt;/p&gt;

&lt;p&gt;Happy hacking! 😉&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>react</category>
      <category>docker</category>
      <category>webdev</category>
    </item>
    <item>
      <title>WordPress REST API as a Back-end with React and Docker (Part 1)</title>
      <dc:creator>Daniel Emod Kovacs</dc:creator>
      <pubDate>Tue, 30 Nov 2021 17:46:47 +0000</pubDate>
      <link>https://dev.to/danielkov/wordpress-rest-api-as-a-back-end-with-react-and-docker-part-1-2gb2</link>
      <guid>https://dev.to/danielkov/wordpress-rest-api-as-a-back-end-with-react-and-docker-part-1-2gb2</guid>
      <description>&lt;h1&gt;
  
  
  About This Project
&lt;/h1&gt;

&lt;p&gt;About a month ago, I was faced with a challenge. At my workplace I was asked to work on a project as a single developer, responsible for the complete technical development of the entire thing, and what’s even better, I was offered a very strict schedule. A little under a month in fact. At first it seemed like a stretch, but it was definitely doable, so I complied. Taking into account the scope of the project and the amount of time I had on my hands I made some snappy decisions about the technologies I was going to use. Here are some of the features I needed to implement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRUD capability on several different types of content (news, media, promotions, etc).&lt;/li&gt;
&lt;li&gt;Multimedia uploads, including files and pictures.&lt;/li&gt;
&lt;li&gt;Different permission groups of users.&lt;/li&gt;
&lt;li&gt;User submitted responses to posts.&lt;/li&gt;
&lt;li&gt;Multi-platform front-end, including a special use case, where the whole software had to behave completely differently on Smart TVs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those all lead to the conclusion, that what was needed is a basic CMS (Content Management System). There are multiple routes to take in this situation, like picking a huge, popular CMS, written by a team of experienced developers, or looking at some cool open source Flavour of the Month style project, usually written in Node JS and Express, or thirdly I could have gone and created my own from scratch, using one of the many languages and back-end technologies that I am proficient in, like Java with Spring Boot, or GoLang and the Gin framework. Assuming that the scope will stay relatively similar to the initial proposal and realising I did not really have time to learn a new CMS or develop my own from scratch, I decided to go the first route and pick the dreaded WordPress platform. I already could do most of what I needed with little to no modifications, it has great support, official forms, a massive community, a &lt;a href="https://w3techs.com/technologies/overview/content_management/all" rel="noopener noreferrer"&gt;third of the Internet using it&lt;/a&gt;, and last but not least a convenient RESTful API, covering most, if not all functionality, meaning I could take advantage of the admin user interface, while being able to deliver something cool and unique to the people using the front-facing interfaces.&lt;/p&gt;

&lt;p&gt;So I needed to decide on two more things. What should I do about the front-end and how should I ensure that my development process stays smooth throughout? The answer to the first one was &lt;a href="https://www.reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; because I ❤️ React, and have been an absolute fan for a long while now, which means I can deliver applications using React as a base very quickly. In terms of development environment I decided to go with &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;. Again, I absolutely 🐋 the simplicity Docker provides, while also reducing overhead by allowing for development and deployment, using the same exact stack.&lt;/p&gt;

&lt;p&gt;In my original project I could not take advantage of Docker once development was done, due to the customer’s reluctancy to deploy with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  In This Part
&lt;/h2&gt;

&lt;p&gt;We will get as far as installing WordPress using a portable Docker Compose setup and looking at how to handle modifications to our installation, being able to modify each file we need.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Steps
&lt;/h2&gt;

&lt;p&gt;First of all I wanted to set up the development environment, before I took a look at any code. The current version of WordPress requires PHP version 5.4, but it is no longer supported, so PHP v7+ is probably a better choice to go with. I also needed to have a MySQL-compliant database, like MySQL Server or MariaDB. To keep things in sync and working within the same virtual network, I decided to use &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;, which is a nice little utility built on top of Docker, that helps organising and connecting images that are related. Compose uses YAML as the format of its configuration, which is sort of easy to work with and is pretty clear on what it does. It follows Docker’s naming convention for most things. At this point I also decided to work with the basic &lt;code&gt;wordpress&lt;/code&gt; image from DockerHub, which is a community where you can get a ton of pre-made images from. For the data image I picked the &lt;code&gt;mysql&lt;/code&gt; image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:5.7&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./db_data:/var/lib/mysql&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress123&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;

  &lt;span class="na"&gt;wordpress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;80:80'&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;WORDPRESS_DB_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db:3306&lt;/span&gt;
      &lt;span class="na"&gt;WORDPRESS_DB_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
      &lt;span class="na"&gt;WORDPRESS_DB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
&lt;span class="na"&gt;volumes: db_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this config file, we see that we are deploying two services: &lt;code&gt;db&lt;/code&gt; and &lt;code&gt;wordpress&lt;/code&gt;. The important thing to note here is the way Docker Compose wires together the virtual network. It provides domains to the services with the names of the service, for example out MySQL Server will be available at &lt;code&gt;mysql://db:3306&lt;/code&gt;, while our WordPress would be reachable at &lt;code&gt;http://wordpress&lt;/code&gt;. Of course outside of the network (which is where we actually are) we can’t see that, so what we need to do is what you’d do with Docker: expose port &lt;code&gt;80&lt;/code&gt;, which is taken by the Apache running within the container to some of our ports, in this example port &lt;code&gt;8000&lt;/code&gt;. This means that we’ll be able to see our WordPress installation at &lt;code&gt;http://localhost:8000&lt;/code&gt; or in cases where Docker is running within a container (like on Windows), we need to use our &lt;code&gt;$DOCKER_IP&lt;/code&gt; variable or something similar.&lt;/p&gt;

&lt;p&gt;Another thing to note is that the &lt;code&gt;db&lt;/code&gt; image has its working folder mapped to a local folder called &lt;code&gt;db_data&lt;/code&gt;. For this to work, we need to create this folder. If there is no such folder, nothing will happen, however it is handy to have all development data saved locally also.&lt;/p&gt;

&lt;p&gt;We can start up this configuration by entering the following command in the directory, where our &lt;code&gt;docker-compose.yml&lt;/code&gt; is saved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The -d flag is handy as it will start the containers in detached mode, meaning we can get log output by using docker-compose logs.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Upon visiting &lt;code&gt;http://localhost:8000&lt;/code&gt;, we should see the following screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftj6x2k6myxb93ig0jxz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftj6x2k6myxb93ig0jxz4.png" alt=" " width="800" height="763"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Screenshot of WordPress install screen&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What’s more, upon completing the famous 5 second install process, whereby giving our credentials, such as username and password both set to &lt;code&gt;admin&lt;/code&gt; (please do not do this in actual production builds), we should be greeted with the below screen upon logging in. Note that if you’ve mounted the volume &lt;code&gt;db_data&lt;/code&gt; to an actual folder, you should see MySQL server spitting out files related to our new WordPress installation. This is cool because you can just bundle this up at a later point and install it under an actual instance of MySQL Server or another Docker image and it will work fine with the same WordPress configurations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0mltn3u6qsm2s40yuze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0mltn3u6qsm2s40yuze.png" alt=" " width="800" height="763"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Screenshot of WordPress admin screen&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Making the WordPress Installation Configurable
&lt;/h2&gt;

&lt;p&gt;The next thing we should probably do is making it so that we can actually change the files that are served via WordPress. This helps because we do want to touch our &lt;code&gt;functions.php&lt;/code&gt; for our own theme, to add custom post types later on.&lt;/p&gt;

&lt;p&gt;For this all we need to do is add the following two lines to our &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./wordpress:/var/www/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like we did with the MySQL service, we also need to add this directory to our workspace, otherwise this will not work.&lt;/p&gt;

&lt;p&gt;Refer to the &lt;code&gt;db&lt;/code&gt; service config if you’re unsure which lines to put this on. We also need to restart our Docker Compose network for these changes to take effect. To do that, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose down&lt;span class="p"&gt;;&lt;/span&gt; docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that there is a &lt;code&gt;docker-compose restart&lt;/code&gt;, but that will not reload configurations sadly.&lt;/p&gt;

&lt;p&gt;A perk of this approach is that because WordPress runs on PHP, which is a run-time evaluated per-invokation scripting language, we can simply update any of the PHP files and press refresh in our browser for immediate effect. This is actually what we’ll be taking advantage of in the next part, where we’ll install plugins, slim down the overall installation size and also start our React project with the REST API.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>react</category>
      <category>docker</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
