<?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: geraldcroes</title>
    <description>The latest articles on DEV Community by geraldcroes (@geraldcroes).</description>
    <link>https://dev.to/geraldcroes</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%2F48844%2F37df06e4-5790-41bd-8346-6da954d6365a.jpg</url>
      <title>DEV Community: geraldcroes</title>
      <link>https://dev.to/geraldcroes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/geraldcroes"/>
    <language>en</language>
    <item>
      <title>Kubernetes &amp; Traefik 101— When Simplicity Matters</title>
      <dc:creator>geraldcroes</dc:creator>
      <pubDate>Wed, 08 Aug 2018 16:47:00 +0000</pubDate>
      <link>https://dev.to/geraldcroes/kubernetes--traefik-101-when-simplicity-matters-6k6</link>
      <guid>https://dev.to/geraldcroes/kubernetes--traefik-101-when-simplicity-matters-6k6</guid>
      <description>&lt;h4&gt;
  
  
  The tutorial that would have spared me hours of struggling with my keyboard
&lt;/h4&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%2Fdo74te2x5swcepo6fni3.jpeg" 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%2Fdo74te2x5swcepo6fni3.jpeg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever been in a situation that started with …&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Someone at work:&lt;/em&gt; “Look, it’s super simple, let me explain …”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… that continued with …&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[ … agony of arcane jargon …]&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Same enthusiastic colleague:&lt;/em&gt; “See, did you get it?”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You (poker face):&lt;/em&gt; “Sure, gotcha, aha, no problem, whoo, super simple indeed, aha … ”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;… but that ended up with you sneaking into the bathroom to babble chunks of keywords you barely remember.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Ok Google, what is a cluster of Ingress in a cube of nodes? … Please please please help me.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nope. Hasn’t happened to me. Not even once. No Sir!&lt;/p&gt;

&lt;p&gt;But let’s &lt;em&gt;pretend&lt;/em&gt; that it did happen (&lt;em&gt;hypothetically&lt;/em&gt;) several years ago, and that all the articles I stumbled upon during my research were made of such cryptic symbols that tears started to come out of my eyes (and they weren’t tears of joy).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I said: Let’s pretend.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So based on this &lt;em&gt;fictional&lt;/em&gt; situation, let’s try to write the easiest tutorial that involves setting up Traefik as an Ingress Controller for Kubernetes. (And I promise: I will explain everything that is not obvious.)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can skip this part if you’re familiar with Kubernetes.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What You Need to Know about Kubernetes
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Kubernetes, as in Cluster
&lt;/h4&gt;

&lt;p&gt;Kubernetes is a cluster technology. It means that you will see a cluster of computers as one entity. You will not deploy an application on a specific computer, but &lt;em&gt;somewhere&lt;/em&gt; in the cluster, and it’s Kubernetes’s job to determine the computer that best matches the requirements of your application.&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%2Fo1btl3uelqm6pzjmqkev.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%2Fo1btl3uelqm6pzjmqkev.png" width="800" height="473"&gt;&lt;/a&gt;Machines in the cluster can have different characteristics&lt;/p&gt;

&lt;h4&gt;
  
  
  Nodes
&lt;/h4&gt;

&lt;p&gt;Each computer in the cluster is called a node. Eventually, the nodes will host your applications. The nodes can be spread throughout the world in different data centers, and it’s Kubernetes’s job to make them communicate as if they were neighbors.&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%2F93ewfzs6m4cw1a7u7c66.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%2F93ewfzs6m4cw1a7u7c66.png" width="800" height="280"&gt;&lt;/a&gt;Nodes are machines in the cluster&lt;/p&gt;

&lt;h4&gt;
  
  
  Containers
&lt;/h4&gt;

&lt;p&gt;I guess that you are already familiar with containers. Just in case you’re not, they used to be the next step of virtualization, and today they are just that: the de-facto standard for virtualization. Instead of configuring a machine to host your application, you have your application wrapped into a container (along with everything your application needs — OS, libraries, dependencies, …) and deployed on a machine that hosts the container engine which is in charge of actually running the containers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Containers technically don’t belong to Kubernetes; they’re just one of the tools of the trade.&lt;/em&gt;&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%2Fo5j17oq4n34z4rgo3jm7.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%2Fo5j17oq4n34z4rgo3jm7.png" width="" height=""&gt;&lt;/a&gt;Container embed the required technologies&lt;/p&gt;

&lt;p&gt;Basically, Kubernetes sees containers like in the following diagram:&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%2Fvf01zh1hgd7d1y40v92x.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%2Fvf01zh1hgd7d1y40v92x.png" width="800" height="332"&gt;&lt;/a&gt;The container engine is responsible for handling the underlying technologies needed in your containers&lt;/p&gt;

&lt;h4&gt;
  
  
  Pods
&lt;/h4&gt;

&lt;p&gt;Because Kubernetes loves layers, Kubernetes adds the notion of Pods around your containers. Pods are the smallest unit you will eventually deploy to the cluster. A single Pod can hold multiple containers, but for the sake of simplicity let’s say for now that a single Pod will host a single container.&lt;/p&gt;

&lt;p&gt;So, in a Kubernetes world, a Pod is the new name for an instance of your application, an instance of your service. Pods will be hosted on the Nodes, and it’s Kubernetes’s job to determine which Node will host which Pod.&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%2Fd73dncl2d4pubc34gbr5.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%2Fd73dncl2d4pubc34gbr5.png" width="800" height="501"&gt;&lt;/a&gt;If a Pod consists of multiple containers, they will share the same resources / network&lt;/p&gt;

&lt;h4&gt;
  
  
  Deployments
&lt;/h4&gt;

&lt;p&gt;Here comes the fun part! Deployments are requirements you give to Kubernetes regarding your applications (your Pods). Basically, with deployments you tell Kubernetes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey Kube, always keep 5 instances (or replicas) of these Pods running — always.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s Kubernetes’s job to ensure that your cluster will host 5 replicas of your Pods at any given time.&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%2Fmlmb53us46xhygb1vlz5.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%2Fmlmb53us46xhygb1vlz5.png" width="800" height="506"&gt;&lt;/a&gt;Kubernetes is responsible for deploying the pods to the right places&lt;/p&gt;

&lt;h4&gt;
  
  
  Services
&lt;/h4&gt;

&lt;p&gt;Oh, yet another fun concept …&lt;/p&gt;

&lt;p&gt;Pods’ lifecycle are erratic; they come and go by Kubernetes’ will.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Not healthy? Killed.&lt;/p&gt;

&lt;p&gt;Not in the right place? Cloned, and killed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;(No, you definitely don’t want to be ruled by Kube!)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So how can you send a request to your application if you can’t know for sure where it lives? The answer lies in services.&lt;/p&gt;

&lt;p&gt;Services define sets of your &lt;em&gt;deployed&lt;/em&gt; Pods, so you can send a request to “whichever available Pod of your application type.”&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%2Fom9ulryhdusj5dcbolg9.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%2Fom9ulryhdusj5dcbolg9.png" width="800" height="522"&gt;&lt;/a&gt;When requesting your application, you don’t care about its location or about which pod answers the request&lt;/p&gt;

&lt;h4&gt;
  
  
  Ingress
&lt;/h4&gt;

&lt;p&gt;So we have Pods in our cluster.&lt;/p&gt;

&lt;p&gt;We have Services so we can talk to them &lt;em&gt;from within&lt;/em&gt; our cluster. (Technically, there are ways to make services available from the outside, but we’ll purposefully skip that part for now.)&lt;/p&gt;

&lt;p&gt;Now, we’d like to expose our Services to the internet so customers can access our products.&lt;/p&gt;

&lt;p&gt;Ingress objects are the rules that define the routes that should exist.&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%2Ffs5mpv5816jjrqdndpbd.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%2Ffs5mpv5816jjrqdndpbd.png" width="800" height="408"&gt;&lt;/a&gt;Ingress objects are the rules that define the routes to our services&lt;/p&gt;

&lt;h4&gt;
  
  
  Ingress Controller
&lt;/h4&gt;

&lt;p&gt;Now that you have defined the rules to access your services from the outside, all you need is a component that routes the incoming requests according to the rules … and these components are called Ingress Controllers!&lt;/p&gt;

&lt;p&gt;And since this is the topic of this article — Traefik is a great Ingress Controller for Kubernetes.&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%2Fap6cm6u6aod9ouh5iaa8.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%2Fap6cm6u6aod9ouh5iaa8.png" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What You Need to Know about Traefik
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It rocks.&lt;/li&gt;
&lt;li&gt;It’s easy to use.&lt;/li&gt;
&lt;li&gt;It’s production ready and used by big companies.&lt;/li&gt;
&lt;li&gt;It works with every major cluster technology that exists.&lt;/li&gt;
&lt;li&gt;It’s &lt;a href="https://github.com/containous/traefik" rel="noopener noreferrer"&gt;open source&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;It’s super popular; more than 150M downloads at the time of writing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;… oh? Is my opinion biased? Well, maybe … but all of the above is true!&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s Start Putting Everything Together!
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;This is the part where we actually start to deploy services into a Kube cluster and configure Traefik as an Ingress Controller.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Prerequisite
&lt;/h4&gt;

&lt;p&gt;You have access to a Kubernetes cluster, and you have &lt;a href="https://kubernetes.io/docs/reference/kubectl/overview/" rel="noopener noreferrer"&gt;&lt;em&gt;kubectl&lt;/em&gt;&lt;/a&gt; that points to that cluster.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Just so you know, here I’m using Kubernetes embedded in&lt;/em&gt; &lt;a href="https://docs.docker.com/docker-for-mac/" rel="noopener noreferrer"&gt;&lt;em&gt;Docker for Mac&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What We’ll Do
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;We’ll use a pre-made container — containous/whoami — capable of telling you where it is hosted and what it receives when you call it. (Sorry to disappoint you, but I can confirm we won’t build the new killer app here^^)&lt;/li&gt;
&lt;li&gt;We’ll define two different Pods, a &lt;em&gt;whoami&lt;/em&gt; and a &lt;em&gt;whoareyou&lt;/em&gt; that will use this container.&lt;/li&gt;
&lt;li&gt;We’ll create a deployment to ask Kubernetes to deploy 1 replica of &lt;em&gt;whoami&lt;/em&gt; and 2 replicas of &lt;em&gt;whoareyou&lt;/em&gt; (because we care more about others than we care about ourselves … how considerate!).&lt;/li&gt;
&lt;li&gt;We’ll define two services, one for each of our Pods.&lt;/li&gt;
&lt;li&gt;We’ll define Ingress objects to define the routes to our services.&lt;/li&gt;
&lt;li&gt;We’ll set up Traefik as our Ingress Controller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And because we love diagrams, here is the picture:&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%2Fof2ueul8b4bcwtgtf1gm.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%2Fof2ueul8b4bcwtgtf1gm.png" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting Up Traefik Using Helm
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://helm.sh" rel="noopener noreferrer"&gt;Helm&lt;/a&gt; is a package manager for Kube and, for me, the most convenient way to configure Traefik without messing it up. (If you haven’t installed Helm yet, &lt;a href="https://docs.helm.sh/using_helm/" rel="noopener noreferrer"&gt;doing so is quite easy&lt;/a&gt; and fits in two command lines, e.g. &lt;em&gt;brew install kubernetes-helm,&lt;/em&gt; and &lt;em&gt;helm init&lt;/em&gt;.)&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%2Fn4mc8pv5nqsooy0hbi9x.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%2Fn4mc8pv5nqsooy0hbi9x.png" width="200" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To set up Traefik, copy / paste the following command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install stable/traefik --set dashboard.enabled=true,dashboard.domain=dashboard.localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the above command line, we enabled the dashboard (&lt;em&gt;dashboard.enabled=true&lt;/em&gt;) and made it available on &lt;a href="http://dashboard.localhost" rel="noopener noreferrer"&gt;http://dashboard.localhost&lt;/a&gt; (&lt;em&gt;dashboard.domain=localhost.domain&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The output of the helm install command line will look like:&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%2Ff7l1pefi3j5xq2nq3ydi.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%2Ff7l1pefi3j5xq2nq3ydi.png" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my case, &lt;em&gt;EXTERNAL-IP&lt;/em&gt; is already available and is &lt;em&gt;localhost&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;EXTERNAL-IP&lt;/em&gt; is the address of the door to my cluster; it is the public address of the Ingress Controller (Traefik).&lt;/p&gt;

&lt;p&gt;And as we said before, we should be able to access the dashboard right away!&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%2Frn7mpuvm96gq5gz8fduf.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%2Frn7mpuvm96gq5gz8fduf.png" width="800" height="431"&gt;&lt;/a&gt;The dashboard shows that Traefik has detected a service (called dashboard.localhost, on the right) and has created a route to it (host:dashboard.localhost, on the left)&lt;/p&gt;
&lt;h4&gt;
  
  
  Let’s Deploy Some Pods!
&lt;/h4&gt;

&lt;p&gt;Now it’s time to deploy our first WhoAmI!&lt;/p&gt;

&lt;p&gt;As a reminder, we want one Pod with one container (&lt;em&gt;containous/whoami&lt;/em&gt;).&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%2Fweh5bkk8mnn00aqz6iu5.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%2Fweh5bkk8mnn00aqz6iu5.png" width="352" height="263"&gt;&lt;/a&gt;Quite a straightforward Pod&lt;/p&gt;

&lt;p&gt;Kubernetes uses yaml files to describe its objects, so we will describe our deployment using one.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;To provide some explanations about the file content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define a “deployment” (&lt;em&gt;kind: Deployment&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;The name of the object is “whoami-deployment” (&lt;em&gt;name: whoami-deployment&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;We want one replica (&lt;em&gt;replicas: 1&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;It will deploy pods that have the label app:whoami (&lt;em&gt;selector: matchLabels: app:whoami&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Then we define the pods (&lt;em&gt;template: …&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;The Pods will have the whoami label (&lt;em&gt;metadata:labels:app:whoami&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;The Pods will host a container using the image containous/whoami (&lt;em&gt;image:containous/whoami&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;📗 Note: You can read more about&lt;/em&gt; &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="noopener noreferrer"&gt;&lt;em&gt;deployments in the Kubernetes documentation.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have described our deployment, we ask Kubernetes to take the file into account with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f whoami-deployment.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And let’s check what happened with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F8s175e3rf67iflxj207a.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%2F8s175e3rf67iflxj207a.png" width="800" height="198"&gt;&lt;/a&gt;The whoami-deployment has been created&lt;/p&gt;
&lt;h4&gt;
  
  
  Let’s Define a Service!
&lt;/h4&gt;

&lt;p&gt;If you remember correctly, we need services so we can talk to “any available Pod” of a given kind.&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%2Fgryg2w35elyzxk1dckje.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%2Fgryg2w35elyzxk1dckje.png" width="352" height="643"&gt;&lt;/a&gt;We need the whoami service to refer to our whoami pods&lt;/p&gt;

&lt;p&gt;Once again, we need to define the object:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Some explanations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define a “service” (&lt;em&gt;kind: Service&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;The name of the object is “whoami-service” (&lt;em&gt;name: whoami-service&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;It will listen on port 80 and redirect on port 80 (&lt;em&gt;ports: ...&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;The target Pods have the label whoami (&lt;em&gt;selector:app:whoami&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;📗 Note: You can read more about&lt;/em&gt; &lt;a href="https://kubernetes.io/docs/tutorials/services/" rel="noopener noreferrer"&gt;&lt;em&gt;services in the Kubernetes documentation.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have described our service, we ask Kubernetes to take the file into account with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f whoami-service.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And let’s check what happened with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fbk8didlg6kpdsgnhf5gd.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%2Fbk8didlg6kpdsgnhf5gd.png" width="800" height="167"&gt;&lt;/a&gt;Our service is available!&lt;/p&gt;
&lt;h4&gt;
  
  
  Ingress
&lt;/h4&gt;

&lt;p&gt;At last, we’re about to define the rules so that the world can benefit from our (kick-ass) service.&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%2F1jgzkwk6jacizfsexjh5.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%2F1jgzkwk6jacizfsexjh5.png" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You know the drill, let’s write the YML file to describe the new object:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Some explanations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define an “ingress” (&lt;em&gt;kind: Ingress&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;The name of the object is “whoami-ingress” (&lt;em&gt;name: whoami-ingress&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;The class of the Ingress is “traefik” (kubernetes.io/ingress.class:traefik). This one is important because it tells Traefik to take this Ingress into account.&lt;/li&gt;
&lt;li&gt;We add rules for this Ingress (rules: …)&lt;/li&gt;
&lt;li&gt;We want requests to host whoami.localhost (host:whoami.localhost) to be redirected to the service whoami-service (serviceName:whoami-service) using http (servicePort: http).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;📗 Note: You can read more about&lt;/em&gt; &lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" rel="noopener noreferrer"&gt;&lt;em&gt;Ingress in the Kubernetes documentation.&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have described our Ingress, we ask Kubernetes to take the file into account with the following (same old) command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f whoami-ingress.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And now, since Traefik is our Ingress Controller, let’s see if something has changed in the dashboard …&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%2F68j87pme40ysdmgc79op.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%2F68j87pme40ysdmgc79op.png" width="800" height="606"&gt;&lt;/a&gt;Traefik has automatically detected the new Ingress!&lt;/p&gt;

&lt;p&gt;That’s it, no reload, no additional configuration file (there were enough). Traefik has updated its configuration and is now able to handle the route whoami.localhost!&lt;/p&gt;

&lt;p&gt;Let’s check …&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%2Fas5ki7b6fa3mawib0tdx.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%2Fas5ki7b6fa3mawib0tdx.png" width="800" height="389"&gt;&lt;/a&gt;Traefik redirects the requests as expected&lt;/p&gt;

&lt;p&gt;Yes, our service is useful, but its UI could use a bit of love ❤️&lt;/p&gt;

&lt;p&gt;Here, we confirm that Traefik &lt;em&gt;is&lt;/em&gt; our Ingress Controller and that it is ready to bring its features to your services!&lt;/p&gt;
&lt;h3&gt;
  
  
  May I Ask For Load Balancing in Action?
&lt;/h3&gt;

&lt;p&gt;Earlier, we talked about a WhoAreYou deployment with 2 replicas.&lt;/p&gt;

&lt;p&gt;Let’s do it in just one file :-)&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;There is not much to say here, except that this time we have 2 replicas … (replicas: 2)&lt;/p&gt;

&lt;p&gt;So let’s ask Kubernetes to apply our new configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f whoareyou.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let’s go right away to Traefik’s dashboard.&lt;/p&gt;

&lt;p&gt;And voilà!&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%2Fxfmidtu4pw4tc962ckq1.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%2Fxfmidtu4pw4tc962ckq1.png" width="800" height="624"&gt;&lt;/a&gt;Traefik detects the new Ingress and the two available Pods in the Service&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%2Fh18ew9ghe4n3dy3wy8fa.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%2Fh18ew9ghe4n3dy3wy8fa.png" width="800" height="397"&gt;&lt;/a&gt;First request, one of the Pod replies&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%2Fzxfkrwf4xx176aqpdu1z.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%2Fzxfkrwf4xx176aqpdu1z.png" width="800" height="397"&gt;&lt;/a&gt;Second request, the other Pod replies&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;If I had wanted to write an article that dealt with “just” configuring Traefik as an Ingress Controller for Kubernetes, well, it would have fit in one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install stable/traefik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because it’s actually the only configuration operation that we’ve needed in the article. The rest is just explanations and demos.&lt;/p&gt;

&lt;p&gt;Yes, this step was indeed as simple as that!&lt;/p&gt;

&lt;h3&gt;
  
  
  Go Further With Traefik!
&lt;/h3&gt;

&lt;p&gt;Now that you know how to configure Traefik, it might be a good time to delve into its documentation and learn about its &lt;a href="https://docs.traefik.io/#features" rel="noopener noreferrer"&gt;other features&lt;/a&gt; (auto HTTPS, Let’s Encrypt automatic support, circuit breaker, load balancing, retry, websocket, HTTP2, GRPC, metrics, etc.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://containo.us" rel="noopener noreferrer"&gt;Containous&lt;/a&gt; is the company that helps Træfik be the successful open-source project it is (and that provides commercial support for Traefik).&lt;/p&gt;

&lt;p&gt;Follow &lt;a href="https://twitter.com/geraldcroes" rel="noopener noreferrer"&gt;me&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/traefikproxy" rel="noopener noreferrer"&gt;Træfik&lt;/a&gt; on Twitter :-)&lt;/p&gt;

&lt;p&gt;Your comments &amp;amp; questions are welcome!&lt;/p&gt;

&lt;p&gt;You can clone the files from my github repository &lt;a href="https://github.com/geraldcroes/kubernetes-traefik-article" rel="noopener noreferrer"&gt;geraldcroes/kubernetes-traefik-article&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>traefik</category>
      <category>kubernetes</category>
      <category>opensource</category>
    </item>
    <item>
      <title>From Chief Enterprise Architect to Developer</title>
      <dc:creator>geraldcroes</dc:creator>
      <pubDate>Tue, 27 Feb 2018 18:04:02 +0000</pubDate>
      <link>https://dev.to/geraldcroes/from-chief-enterprise-architect-to-developer-4e1n</link>
      <guid>https://dev.to/geraldcroes/from-chief-enterprise-architect-to-developer-4e1n</guid>
      <description>&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%2F7kajmnprsz1343oc36mt.jpeg" 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%2F7kajmnprsz1343oc36mt.jpeg" width="800" height="533"&gt;&lt;/a&gt;Photo by Gerald Croes — Mini World Lyon&lt;/p&gt;

&lt;p&gt;You’ve read the title right, I’ve quit my (dream) job — CEA — for a new job — developer.&lt;/p&gt;

&lt;p&gt;Now, I’ll wait a minute for the information to sink in.&lt;/p&gt;

&lt;p&gt;…yes, that’s what I did.&lt;/p&gt;

&lt;p&gt;All things considered, I might need a minute for myself too.&lt;/p&gt;

&lt;p&gt;…Ok, that’s what &lt;em&gt;I&lt;/em&gt; did.&lt;/p&gt;




&lt;p&gt;Seriously, how did that ever happen?&lt;/p&gt;




&lt;p&gt;I think that it has to do with the way I got involved in IT.&lt;/p&gt;

&lt;p&gt;Years ago, I stumbled onto programming thanks to laziness — a native skill I managed to nurture to undiscovered levels of mastery back when I was a teenager.&lt;/p&gt;

&lt;p&gt;Because I didn’t like wasting my time doing homework (who does?), I was drawn to buy a fancy calculator that had far more buttons than one would need to pilot a plane. “If it has more buttons, it must do more things.” Laziness having its limits, guessing the roles of each button turned out to be quite ineffective, so I had to (grudgingly) open the 500-page manual … where a chapter caught my attention — &lt;em&gt;Programming Your Calculator.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Of course, buying a calculator doesn’t make you an “IT guy/gal”, at least no more than having acne during your teens or being socially awkward when standing in a 5-meter radius of a person of the opposite sex (even if both can help).&lt;/p&gt;

&lt;p&gt;So the extra factor that came into play was my math teacher who, casting a glance at my new device, stared at me with a smirk, “Don’t put high hopes in &lt;em&gt;that&lt;/em&gt; because it will prove to be useless when working on matrixes. I’m interested in the reasoning, in &lt;em&gt;every step&lt;/em&gt; leading to the result, &lt;em&gt;not&lt;/em&gt; by the result itself.”&lt;/p&gt;

&lt;p&gt;Challenge … accepted!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No, the matrix wouldn’t have me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I eagerly went back to the manual and started to learn programming. If it were possible, I would make &lt;em&gt;that&lt;/em&gt; show &lt;em&gt;every step&lt;/em&gt; leading to the result.&lt;/p&gt;

&lt;p&gt;And guess what?&lt;/p&gt;

&lt;p&gt;Worked like a charm.&lt;/p&gt;

&lt;p&gt;I managed to get the maximum mark for the test (in 15 minutes instead of the four scheduled hours), and I also managed to get calculators banned for the entire class. (No, didn’t see that coming.)&lt;/p&gt;

&lt;p&gt;Anyway, I was hooked. I started to program everything I was taught instead of talking regular notes (whether I would have the calculator for the tests or not). The funny thing is that my math teacher and I started to get along together because I had been transformed into the most benevolent student, asking questions about every detail and edge-case about the formulas we were taught.&lt;/p&gt;

&lt;p&gt;At the end of the year, I had become good at working harder to do less … although in the end I am not sure if I actually worked less than if I had been willing to do more.&lt;/p&gt;

&lt;p&gt;The story could have stopped there and then, but one day, as I was facing every students’ dreaded conundrum (What do you want to do in the future?), I discovered the most unbelievable thing— “You know, if you like programming, you could do that for a living … I mean … work in IT.”&lt;/p&gt;

&lt;p&gt;Developer was an actual job. People were getting paid for programming.&lt;/p&gt;

&lt;p&gt;Not so dazzling when you remember that kicking in a ball is also a job, but great news nonetheless for someone who has two left feet.&lt;/p&gt;

&lt;p&gt;Anyway, I went to an IT school and learned programming (for real).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Choose a job you love and you’ll never have to work a single day.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After graduation, I joined a consulting agency and worked on many different projects.&lt;/p&gt;

&lt;p&gt;Out of habit, I kept working during my free time to get rid of tasks I didn’t enjoy during the day. I learned new (and more concise) programming languages, I developed an IDE with code completion and macro recording, I wrote a framework that handled routing, security, templating and that had an embedded ORM, I tinkered with a dependency injection framework, I met design patterns, I programmed code generators, packaged reusable modules, designed a content management system, and so on.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I did all this during my free time … so I’d have more fun during work hours.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And since I had gathered so much experience (working extra hours), I started to share my knowledge with my teammates … and it became part of my new job.&lt;/p&gt;

&lt;p&gt;Habits being habits, I started to read books about optimizing teamwork, learned about agile methods, about dozens of tools that would help us improve our delivery … and since I had managed to put all this together … it became part of my new job.&lt;/p&gt;

&lt;p&gt;Habits being habits … well, you get the drill … it became part of my new job … and I ended up being CEA.&lt;/p&gt;

&lt;p&gt;But the more I became involved in business and management, the more I began drifting away from code. The more I was using the whiteboard, the more wistfully I looked at my keyboard. The more I was a CEA, the less I was in touch with &lt;em&gt;why&lt;/em&gt; I got involved in IT.&lt;/p&gt;

&lt;p&gt;But one day, a friend of mine disclosed the most unbelievable thing — “You know, if you like programming so much, it’s still a job … ”&lt;/p&gt;

&lt;p&gt;So it became my new job, and I’m quite excited.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>The Good (Tweak), the Bad (Mac), and the Ugly (Terminal)</title>
      <dc:creator>geraldcroes</dc:creator>
      <pubDate>Sun, 25 Feb 2018 17:11:09 +0000</pubDate>
      <link>https://dev.to/geraldcroes/the-good-tweak-the-bad-mac-and-the-ugly-terminal-3eg3</link>
      <guid>https://dev.to/geraldcroes/the-good-tweak-the-bad-mac-and-the-ugly-terminal-3eg3</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--71qB8T6m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ATwaNryU2UWiaCufqOq2RaA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--71qB8T6m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ATwaNryU2UWiaCufqOq2RaA.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I’ve switched to Mac … for work …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There, I’ve said it.&lt;/p&gt;

&lt;p&gt;It feels like confessing a fault. A confession where forgiveness doesn’t ensue. A confession where what follows is contempt, contempt in my (Linux-minded) colleagues’ eyes. So I’ll just give them a good reason ...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;… and so far I’m enjoying it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even though I’m a big Linux fan, I’m used to working with a bunch of applications that are not available there, and the Mac (despite the steep price) appeared as an alternative to the virtual-machines hell. Far from being perfect, it’s a good balance between a Unix system and an end-user general-purpose machine.&lt;/p&gt;

&lt;p&gt;However, coming from Linux, the jarring out-of-the-box experience with the terminal was a shock. The default setup is just plain terrible — outdated, no autocompletion, no colors … no fun.&lt;/p&gt;

&lt;p&gt;But after a few tweaks I’m feeling at home, and this article is all about sharing configuration options so that people like me will keep enjoying their beloved command lines.&lt;/p&gt;

&lt;p&gt;Here is our starting point.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bu-pszHX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AewtkWxuMfrtVA1d76o5TfA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bu-pszHX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AewtkWxuMfrtVA1d76o5TfA.png" alt=""&gt;&lt;/a&gt;People don’t like the terminal … you don’t say!&lt;/p&gt;

&lt;h3&gt;Step 1 — Homebrew&lt;/h3&gt;

&lt;p&gt;Because there is a life beyond the App Store, your first step on Mac should be to install Homebrew. It’s not mandatory; it just makes your life easier (you decide).&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://brew.sh"&gt;its website&lt;/a&gt;, Homebrew is the “Missing package manager for Mac.”&lt;/p&gt;

&lt;p&gt;In Linux words, it’s our &lt;em&gt;apt&lt;/em&gt;, &lt;em&gt;yum&lt;/em&gt;, &lt;em&gt;dnf&lt;/em&gt;, or &lt;em&gt;pkg&lt;/em&gt; (depending on where you come from).&lt;/p&gt;

&lt;p&gt;Installing Homebrew is a one-liner:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;h4&gt;Done, but Nothing Has Changed&lt;/h4&gt;

&lt;p&gt;Exactly, nothing has changed, except that you’ll be able to install, update, and remove the other tools we’ll talk about in a minute.&lt;/p&gt;

&lt;h3&gt;Step 2 — Update Bash to Version 4.4&lt;/h3&gt;

&lt;p&gt;Supposedly because of licensing issues (GPLv2 vs. GPLv3), the bash that comes with our Macs is stuck in 2007 (version 3.2).&lt;/p&gt;

&lt;p&gt;Let’s fix this and update to version 4.4 (at the time of this writing).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;brew install bash&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, it’s that simple.&lt;/p&gt;

&lt;h4&gt;Configure Bash 4.4 as Your Default Bash&lt;/h4&gt;

&lt;p&gt;Now that you have the newer version of Bash installed, you need to tell your terminal to use it instead of the default login shell.&lt;/p&gt;

&lt;p&gt;Open the terminal preferences and set the “Shells open with” option so that it points to your new best friend, &lt;em&gt;/usr/local/bin/bash&lt;/em&gt;, which is the location where Homebrew has installed it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SbT9Qwc1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_GwAGVqN-JLoJ5spB2Fy1A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SbT9Qwc1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_GwAGVqN-JLoJ5spB2Fy1A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, for a reason I have yet to understand, you need to add that same path to your &lt;em&gt;/etc/shells&lt;/em&gt; file. If you don’t, you might stumble upon small issues (e.g. I wasn’t able to make my terminal play along with &lt;a href="https://www.alfredapp.com"&gt;Alfred&lt;/a&gt;).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Restart your terminal and type &lt;em&gt;bash --version&lt;/em&gt; to check that everything works as expected (you can also try to &lt;em&gt;echo $BASH_VERSION&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oUStm2D_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_Mvs5WCfoCazcbJsDAQZtQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oUStm2D_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_Mvs5WCfoCazcbJsDAQZtQ.png" alt=""&gt;&lt;/a&gt;The terminal now has Bash 4.4 by default.&lt;/p&gt;

&lt;h3&gt;Step 3 — The Colors of Bash&lt;/h3&gt;

&lt;p&gt;To steer clear of the dim monochrome corner Apple wants you to stay in, enable the colors.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;vi ~/.bash_profile&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Take this new configuration file into account (&lt;em&gt;source ~/.bash_profile&lt;/em&gt;) and see for yourself :-)&lt;/p&gt;

&lt;h4&gt;&lt;strong&gt;Before&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DgeNWRGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AGAUIohm0kWeZDoEXQv6bLg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DgeNWRGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AGAUIohm0kWeZDoEXQv6bLg.png" alt=""&gt;&lt;/a&gt;Life in green.&lt;/p&gt;

&lt;h4&gt;After&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sV92CVMb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ApgaXbl4_XPGdMnNwdX3BTA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sV92CVMb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ApgaXbl4_XPGdMnNwdX3BTA.png" alt=""&gt;&lt;/a&gt;Not much on this screenshot, except that the colors for directories and regular files are now different.&lt;/p&gt;

&lt;h3&gt;Step 4 — Autocomplete Time&lt;/h3&gt;

&lt;p&gt;It’s time to allow your fingers to rest and let them enjoy the power of the tab key for a bit of auto-completion (that goes beyond file names).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;brew install bash-completion&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now update your &lt;em&gt;.bash_profile&lt;/em&gt; (&lt;em&gt;vi ~/.bash_profile&lt;/em&gt;), and add the following line&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[-f /usr/local/etc/bash_completion] &amp;amp;&amp;amp; . /usr/local/etc/bash_completion&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you need autocompletion for Git, you’ll need to install or update it (the version provided with XCode doesn’t work with the completion).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;brew install git&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And as usual, restart your terminal if you want to test it right away.&lt;/p&gt;

&lt;h3&gt;Step 5 — May I Ask for a Git Prompt?&lt;/h3&gt;

&lt;p&gt;If you use Git, the one thing still missing from your now-good-looking terminal is a Git prompt with the state of your repository and the branch you’re on.&lt;/p&gt;

&lt;p&gt;Once again, you’re just a single brew command away from the solution.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;brew install bash-git-prompt&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To load its configuration at startup, you need to add the following lines into your &lt;em&gt;.bash_profile&lt;/em&gt; file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;vi ~/.bash_profile&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;You now have a nice Git prompt you can configure to your taste.&lt;/p&gt;

&lt;h4&gt;What It Looks Like in a Non-Git Directory&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8lejRyfo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AjfxNxQfykQCIFYbHQmLikg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8lejRyfo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AjfxNxQfykQCIFYbHQmLikg.png" alt=""&gt;&lt;/a&gt;The green tick means that the last command has been successful.&lt;/p&gt;

&lt;h4&gt;What It Looks Like in a Git Directory&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P4E8hZRF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A9Jf83cAq4hzCdsS_4yCdww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4E8hZRF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A9Jf83cAq4hzCdsS_4yCdww.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that I’m on the master branch and that everything is synchronized with the distant repository.&lt;/p&gt;

&lt;h4&gt;Tune It a Bit More&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://github.com/magicmonty/bash-git-prompt"&gt;bash-git-prompt&lt;/a&gt; package comes with multiple configuration options. To test them out, you can create a &lt;em&gt;~/.git-prompt-colors.sh&lt;/em&gt; file. For what it’s worth, here is mine below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Kh5E7HV---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AEuSYqdXk_RKPMUnvGNFqiQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kh5E7HV---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AEuSYqdXk_RKPMUnvGNFqiQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;My Pimped Out Terminal&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;With a pinch of transparency and a nice background texture, here is what my own terminal looks like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y2ncTuGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AaLLO_4RFXaM2VEZI7ZTv1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y2ncTuGG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AaLLO_4RFXaM2VEZI7ZTv1g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you’ve enjoyed the tour and that you have learned a trick or two to make your terminal a better experience.&lt;/p&gt;

&lt;p&gt;You can download my configuration &lt;a href="https://github.com/geraldcroes/macbook-terminal"&gt;from Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have some tips you’d like to share with a new Mac user, make sure to add them in the comments section.&lt;/p&gt;


</description>
      <category>mac</category>
      <category>terminal</category>
      <category>bash</category>
      <category>git</category>
    </item>
    <item>
      <title>DDD 101 — The 5-Minute Tour</title>
      <dc:creator>geraldcroes</dc:creator>
      <pubDate>Sat, 24 Feb 2018 05:17:34 +0000</pubDate>
      <link>https://dev.to/geraldcroes/ddd-101--the-5-minute-tour-1e9</link>
      <guid>https://dev.to/geraldcroes/ddd-101--the-5-minute-tour-1e9</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Fj5jr5trstvqohtm5l3bl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fj5jr5trstvqohtm5l3bl.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like crazy challenges.&lt;/p&gt;

&lt;p&gt;During a conference in Paris, after the organizers asked me to fulfill a missing-speaker slot for a lightning talk (an hour before the presentation time), not only did I accept, but I decided that an introduction to DDD (Domain Driven Design) was a good choice. Yes, DDD — the discipline that was born in a 560-page book.&lt;/p&gt;

&lt;p&gt;Unfortunately, even if I had managed to get the attention of a room crowded with (PHP!) developers to talk about a topic that was dear to my heart, I don’t know if the presentation insisted enough on the two key aspects that &lt;em&gt;are&lt;/em&gt; DDD.&lt;/p&gt;

&lt;p&gt;My goal with this article is to give it another try, with more time to prepare.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;DD What?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Before you leave, driven away from this article by your acronym-o-phobia syndrome, you might want to know that DDD is full of shiny new design patterns. Design patterns … The funny thing is that they are the reason why I was drawn into this world in the first place … and the funniest thing is that they are the least essential elements in that world.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;So, What Is DDD?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;When I’m using my keyboard, cradled by the sound of the stroke keys, I like to understand the code I’m writing (easy), to understand the code I wrote the day before (less so), to understand the code I wrote six months before (challenging), and the satisfaction that tops the list is to see &lt;em&gt;other&lt;/em&gt; developers understand the code &lt;em&gt;I&lt;/em&gt; wrote.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any fool can write code that a computer can understand. Good programmers write code that humans can understand.&lt;/p&gt;

&lt;p&gt;— Refactoring: Improving the Design of Existing Code, 1999&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My best memory on the subject happened years ago. At the time, I had asked a developer in the team to add a feature to the application. I didn’t give her many details about how the code was organized, and when she came back, a bit puzzled, she asked for confirmation, “All I have to do is to add some lines here and there … and I’m done, right?”&lt;/p&gt;

&lt;p&gt;She couldn’t have been more right. It was amazing to know that the object model I had come up with worked just as expected — on the first read.&lt;/p&gt;

&lt;p&gt;To me, that’s what Domain Driven Design is all about — expressing a meaningful object-oriented model that says what it does.&lt;/p&gt;

&lt;p&gt;DDD reminds you of common sense rules, and it offers a set of ideas, principles, and patterns to make it happen.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;What Sets DDD Apart From Standard OOP?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Good question — nothing.&lt;/p&gt;

&lt;p&gt;DDD is nothing more than OOP applied to business models. (You’ll prove me wrong when you dive deeper into DDD, but let’s accept that as an answer for now.)&lt;/p&gt;

&lt;p&gt;I’ll use my personal experience to try to explain why I believe that DDD &lt;em&gt;is&lt;/em&gt; plain OOP.&lt;/p&gt;

&lt;p&gt;When I first learned about DDD, I was already an enthusiastic OOP practitioner, and I used to advocate about OOP a lot (giving talks, practicing pair reviews, and so on).&lt;/p&gt;

&lt;p&gt;Even though at the time I was considered a satisfactory developer, I knew deep down that &lt;em&gt;something&lt;/em&gt; was wrong with my code, &lt;em&gt;something&lt;/em&gt; I couldn’t figure out, &lt;em&gt;something&lt;/em&gt; that had to do with my inability to write meaningful unit tests that covered the &lt;em&gt;business rules&lt;/em&gt;. I knew that the tales my code were telling were not as expressive as I wished they were.&lt;/p&gt;

&lt;p&gt;But since no one seemed to complain, I kept learning patterns, and patterns, and patterns.&lt;/p&gt;

&lt;p&gt;Before I bought the “blue book” (Domain Driven Design: Tackling Complexity in the Heart of Software), I scanned through the pages and saw factories, repositories, value objects, entities, and this incredibly appealing schema that would lure any geek’s attention.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fe1j9jguizahum16u673c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fe1j9jguizahum16u673c.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They alone convinced me to invest my time (and money) into the book. Even though I was eager to learn about new fancy patterns, I managed to contain my impatience and read the introduction.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Ubiquitous Language&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I don’t remember every word of this infamous reference, nor do I remember every rule, but I remember being hooked right from the beginning. The concept of the ubiquitous language was a revolution.&lt;/p&gt;

&lt;p&gt;Despite a convoluted designation, the idea is straightforward — call a spade a spade. And the underlying rule is, “To know what a spade is; how to use it; what it does … ask someone who knows.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F1rlnaoafcxubfgcd3x01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1rlnaoafcxubfgcd3x01.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Oh, my! Did you enjoy the book just because of this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, it might sound obvious, but &lt;em&gt;this&lt;/em&gt; was the main issue that impaired my ability to write self-explanatory code. Don’t mock me, I can say from experience that I wasn’t alone (and that not everyone has been cured).&lt;/p&gt;

&lt;p&gt;How many of us, developers, have just peeked at the requirements only to start coding right away? How many programmers have skimmed through the business rules to jump on the framework-y and database-ish aspect of the project? Don’t pretend — I know for sure!&lt;/p&gt;

&lt;p&gt;I can’t blame us. These requirements are often a bland and boring read, at least as bland and boring as it is to write them (it’s called karma).&lt;/p&gt;

&lt;p&gt;Good news is that it doesn’t have to be this way.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Only What You Understand Can You Explain&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To be able to solve a problem, I have to understand it (along with its intricacies).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you can’t explain it to a six-year-old, you don’t understand it yourself.&lt;/p&gt;

&lt;p&gt;— Albert Einstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The corollary to that is, “To understand a problem, I have to interview the people that are dealing with it.”&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Agile Methods Certified&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;“Talking to the right people.” That sounded familiar.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Individuals and interactions&lt;/strong&gt; over processes and tools&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Working software&lt;/strong&gt; over comprehensive documentation&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Customer collaboration&lt;/strong&gt; over contract negotiation&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Responding to change&lt;/strong&gt; over following a plan&lt;/p&gt;

&lt;p&gt;— The Agile Manifesto&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course, if you took programming because you’d rather talk to computers over human beings, that can be a harsh truth to swallow. But, if you were looking for the perfect occasion to socialize and stop acting like an &lt;a href="https://en.wikipedia.org/wiki/The_IT_Crowd" rel="noopener noreferrer"&gt;IT Crowd&lt;/a&gt; stereotype, good news, here is your chance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No More Dull Projects&lt;/p&gt;

&lt;p&gt;“Talk to business people; they’ll enjoy explaining their jobs and problems, you’ll love listening and finding solutions.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It literally changed my vision of IT.&lt;/p&gt;

&lt;p&gt;As a young developer, thrilled by the idea of crunching technical puzzles, I was often disappointed by the lack of challenges brought by real-life projects. No, calculating a price for an insurance plan is not what I call challenging … nor is finding the cheapest hotel room on a given date … you only spend time writing something you’ve figured out in seconds.&lt;/p&gt;

&lt;p&gt;But when you talk to the business people who need your skills to find a solution and save some time or increase the quality of their output, it all becomes interesting because you get a sense of &lt;em&gt;purpose&lt;/em&gt;. Not only will you write the code for the solution, but you will be part of the solution itself, you’ll know its whys, whats, and whens … and the challenge will be to write it in a way that exposes that very purpose.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;i Shall Not Pass! (Nor Should j or x.)&lt;/strong&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;“You should name a variable using the same care with which you name a first-born child.”&lt;/p&gt;

&lt;p&gt;― Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The above quote resonates even more with the ubiquitous language concept. Each class, each method, each variable should be carefully named so that the story they tell is the business story you’re writing. And heed DDD’s words, “These names should be agreed on with the business.” Why? Because in the future, when you talk about a new feature or a bug report, you’ll understand each other. The code reflects business reality.&lt;/p&gt;

&lt;p&gt;If anyone ever needs to be persuaded that meaningful variable names are mandatory, just ask them.&lt;/p&gt;

&lt;p&gt;Which of the following would you rather read?&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;or&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To this day, no one has ever missed the point … except for one person, “Nope, I would never ever write or read anything in PHP.”&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Health Check — Anemic or Not?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;But let’s go back on track. We’ve said that DDD was OOP applied to the business model. Naturally, after I had read the book, I asked myself this simple question.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is my object model a real object model? Or is this procedural code in disguise?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And I realized that I used to focus all my efforts on the data, without proper dedication to the processes that come along, and that I suffered the &lt;a href="https://en.wikipedia.org/wiki/Anemic_domain_model" rel="noopener noreferrer"&gt;anemic model syndrome&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The fundamental horror of this anti-pattern is that it’s so contrary to the basic idea of object-oriented designing; which is to combine data and process them together. The anemic domain model is just a procedural style design […]. What’s worse, many people think that anemic objects are real objects, and thus completely miss the point of what object-oriented design is all about.&lt;/p&gt;

&lt;p&gt;— Martin Fowler — &lt;a href="https://www.martinfowler.com/bliki/AnemicDomainModel.html" rel="noopener noreferrer"&gt;Martin Fowler’s Bliki&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To self-diagnose my code’s disorder, I asked myself, “Can I replace all my objects with hashmaps? Will my code work after that?” And the answer was a stark yes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxjvtjvp3xlvsztfnmw0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxjvtjvp3xlvsztfnmw0e.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had developed the habit of setting apart data and intelligence — which is contrary to the creed of object-oriented programming — which explained why I often ended up having hundreds of services manipulating dumb data objects … with fat controllers trying to orchestrate the resulting mess.&lt;/p&gt;

&lt;p&gt;DDD’s rule of thumb — Bind data and intelligence together …&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;… And Set Boundaries to Keep Them Apart&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;At this point, two major concepts had finally sunk in — I was talking to business people so that the code would reflect their problems, and I was modeling the solution using real objects.&lt;/p&gt;

&lt;p&gt;Though, as the project grew, I still had two hurdles to overcome: conflicts and complexity.&lt;/p&gt;

&lt;p&gt;Conflicts when we tried to find names for similar concepts used in different contexts, and complexity as the model started to include more intelligence.&lt;/p&gt;

&lt;p&gt;The easiest-to-explain example that comes to my mind is &lt;em&gt;Client&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ClientForTheLogisticTeam, ClientForTheMarketingTeam, ClientForTheAccountingTeam, …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem at hand was that &lt;em&gt;Client&lt;/em&gt; was the actual name used by the business teams, but that very name implied rules and constraints that depended on the context. Our first reflex was to differ from the real names, but the rule is to stick to the business vocabulary.&lt;/p&gt;

&lt;p&gt;Then, we remembered another key point of DDD — &lt;a href="https://martinfowler.com/bliki/BoundedContext.html" rel="noopener noreferrer"&gt;Bounded Contexts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F4lpwrhmvzuut2onauafs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F4lpwrhmvzuut2onauafs.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bounded contexts are the &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" rel="noopener noreferrer"&gt;Single Responsibility Principle&lt;/a&gt; applied to your domain model. Each part of your system has its intelligence, data, and vocabulary. Each part is independent of one another.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is It Time We Talk About Patterns?
&lt;/h3&gt;

&lt;p&gt;Oh, patterns … I had almost forgotten.&lt;/p&gt;

&lt;p&gt;Yes, DDD brings its lot of patterns. Brace yourself; you’re on the brink of learning them in a breeze.&lt;/p&gt;

&lt;p&gt;You model your business using &lt;em&gt;Entities&lt;/em&gt; (the ID matters) and &lt;em&gt;Value Objects&lt;/em&gt; (the values matter). You use &lt;em&gt;Repositories&lt;/em&gt; to retrieve and store them. You create them with the help of &lt;em&gt;Factories&lt;/em&gt;. If an object is too complex for a single class, you’ll create &lt;em&gt;Aggregates&lt;/em&gt; that will bind &lt;em&gt;Entities&lt;/em&gt; &amp;amp; &lt;em&gt;Value Objects&lt;/em&gt; under the same root. If a business logic doesn’t belong to a given object, you’ll define &lt;em&gt;Services&lt;/em&gt; that will manipulate the involved elements. Eventually, when the state of the business changes (a change that matters to business experts), you’ll publish &lt;em&gt;Domain Events&lt;/em&gt; to communicate the change.&lt;/p&gt;

&lt;p&gt;There you are, we’ve talked about DDD patterns!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;But in the End … *This* Is DDD&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.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%2F77bwwwrznhpns6jo6g82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F77bwwwrznhpns6jo6g82.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The rest is not important.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further Readings
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;As its name implies, &lt;a href="https://www.infoq.com/minibooks/domain-driven-design-quickly" rel="noopener noreferrer"&gt;Domain Driven Design Quickly&lt;/a&gt; is an easy but comprehensive read to start learning DDD.&lt;/li&gt;
&lt;li&gt;Of course, &lt;em&gt;Domain Driven Design: Tackling Complexity in the Heart of Software&lt;/em&gt;, by Eric Evans, the book that started it all.&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>domaindrivendesign</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Kotlin Fun With The Factory Pattern</title>
      <dc:creator>geraldcroes</dc:creator>
      <pubDate>Sun, 10 Dec 2017 20:09:37 +0000</pubDate>
      <link>https://dev.to/geraldcroes/kotlin-fun-with-the-factory-pattern-1nmb</link>
      <guid>https://dev.to/geraldcroes/kotlin-fun-with-the-factory-pattern-1nmb</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YpdY19dv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ac_5J7SGs24bGbFFjzf8wWw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YpdY19dv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ac_5J7SGs24bGbFFjzf8wWw.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you read “let’s have some fun with the factory pattern”, I agree that you should doubt the writer’s enthusiasm and see for yourself. But, as I was writing some code to play with this language I’ve recently fallen in love with, I asked myself, “How should I write a factory method?”&lt;/p&gt;

&lt;p&gt;This simple question led me to some experimentations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ok to have some fun, but … what’s a factory?
&lt;/h3&gt;

&lt;p&gt;For those in need of a reminder, the factory is a creational pattern listed in the book commonly referred to as “the GOF”. If you haven’t heard or read about it, there’s still time to catch up. If it falls in the TL;DR category, don’t hesitate to google the world of patterns; there are plenty of resources available on the internet (and Wikipedia is a satisfactory one for a quick introduction).&lt;/p&gt;

&lt;p&gt;The factory’s goal is to deliver a ready-to-use object to its client. The factory hides the complexity of creating and selecting the right object for the job.&lt;/p&gt;

&lt;p&gt;As we’re all fond of UML, I’ll sketch something that vaguely looks like UML (on a Saturday night) so we’re on the same page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bI9F7aah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/601/1%2AyUDdxb-0B6eGrL9UmIHgRw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bI9F7aah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/601/1%2AyUDdxb-0B6eGrL9UmIHgRw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Factory as it is in the GOF
&lt;/h3&gt;

&lt;p&gt;Now that we all remember what a factory is (I know you knew it — but just in case), let’s write the first candid Kotlin implementation.&lt;/p&gt;

&lt;p&gt;Say we have a &lt;em&gt;product&lt;/em&gt; called a FileParser that we need so that we can read information from files we would otherwise be oblivious to.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;And let’s say that we have two available implementations of this FileParser, one dedicated to understanding XML (XmlFileParser) and one dedicated to understanding JSON (JsonFileParser).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;So we’re done with our products description.&lt;/p&gt;

&lt;p&gt;The client (our program) will need one of the two available implementations. To make the right choice, the logic is to test the filename and test its extension. If it’s “.xml”, use XmlFileParser, if it’s “.json”, use JsonFileParser. To avoid testing this everywhere in the code, we have decided to use the factory pattern that, thanks to its createFromFileName(fileName: String) method, will give us the correct FileParser…&lt;/p&gt;

&lt;p&gt;…which is implemented at lightning speed thanks to Kotlin.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;There we are — we have a to-the-letter implementation of a factory in Kotlin.&lt;/p&gt;

&lt;p&gt;If we wanted to use the factory, we’d have written:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;h3&gt;
  
  
  You said it would be fun…
&lt;/h3&gt;

&lt;p&gt;Yes, I know what I said, so let’s keep diving into the subject.&lt;/p&gt;

&lt;p&gt;What’s a bit boring with our factory is that we need to instantiate it. It’s not a lot of lines, but still. I’d love to be able to write something like&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;One line shorter … yes … it’s worth it!&lt;/p&gt;

&lt;p&gt;The syntax looks like a static call, but as there is no “static stuff” in Kotlin, we’ll use a different trick — &lt;em&gt;companion object&lt;/em&gt;. These objects are kinds of &lt;em&gt;singletons&lt;/em&gt; attached to the class (see &lt;a href="https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects"&gt;companion objects in the documentation&lt;/a&gt;).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Now we can use the previous syntax, and it’ll work. But the caveat is that we can no longer call the createFromFileName method from an instance of our FileParserFactory, only from the class itself with a static-like call.&lt;/p&gt;

&lt;p&gt;And if you carefully read the code, you’ll see that our class doesn’t implement FileParserFactory, our &lt;em&gt;companion object&lt;/em&gt; does.&lt;/p&gt;

&lt;p&gt;Of course, we could write a sort of synonym for our instance to be able to expose such a method, but that would be ruining the concept. See for yourself:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;If you’re asking yourself, “What’s wrong with having the static syntax as your only option?” I’ll answer with the simple, “It’s wrong because you can’t pass an instance of your factory to another object. Every client of the factory will have to be hardwired to the implementation of your CompanionObjectFactory.”&lt;/p&gt;

&lt;h3&gt;
  
  
  So … are we having fun yet? Just asking.
&lt;/h3&gt;

&lt;p&gt;Er … Ok, let’s try another syntax.&lt;/p&gt;

&lt;p&gt;If we still want to save a line of code while creating our FileParser, we can use another Kotlin feature, which is the &lt;em&gt;object&lt;/em&gt; keyword. The object keyword is a way of asking your code to ensure that only one instance of a class will be available at any time in the life cycle of your application.&lt;/p&gt;

&lt;p&gt;Let’s see how it’s done.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Yes, we’ve just replaced the &lt;em&gt;class&lt;/em&gt; keyword by the &lt;em&gt;object&lt;/em&gt; keyword.&lt;/p&gt;

&lt;p&gt;From now on, we can use the one line option along with the possibility of calling the method from the instance itself.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;I’m thrilled, my head is spinning right now…&lt;/p&gt;

&lt;p&gt;Man you’re tough. Let’s try to spice things up then.&lt;/p&gt;

&lt;p&gt;So, we have these FileParserFactories that handle the creation of FileParsers. That’s nice, but it would be nicer if we could embed the factory within the FileParser interface itself. Good news: in Kotlin, we can add a &lt;em&gt;companion object&lt;/em&gt; to an interface.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Isn’t that fun? (At least for someone who comes from Java.)&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Once again, we cannot give the factory instance to another object, but … is it still needed as the interface itself embeds its own factory? I agree that this very question is open to debate (because I do not fully agree with myself right now — I’m just getting carried away with the Kotlin syntax).&lt;/p&gt;

&lt;h3&gt;
  
  
  But if I need a different factory? How can I…
&lt;/h3&gt;

&lt;p&gt;Hey! Excellent question.&lt;/p&gt;

&lt;p&gt;The super fun thing with Kotlin is that you can add extensions to existing code. So if you need to write your specific factory, you can add it like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Yes, you’re “adding” a new method to the &lt;em&gt;companion object&lt;/em&gt; within the interface, so from now on you will be able to call the new &lt;em&gt;factory&lt;/em&gt; (fromFile) you’ve just declared.&lt;/p&gt;

&lt;h3&gt;
  
  
  More fun with a fun syntax
&lt;/h3&gt;

&lt;p&gt;Imagine that you could write&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Well, actually you can, by adding the keyword infix before your extension :-)&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Infix means that you don’t need to call the method using the traditional syntax, you can call it the fancy way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Well yeah … why not a factory method in the String itself?
&lt;/h3&gt;

&lt;p&gt;You don’t say! Let’s do this :-)&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;So we can now create a FileParser using this syntax&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;h3&gt;
  
  
  That’s all the fun you’ll get for now
&lt;/h3&gt;

&lt;p&gt;I’m sure there are many other ways to write crazy factories in Kotlin, but I was happy to share these ideas as I played with the language. If you want to tinker with the examples, you’ll find them in &lt;a href="https://github.com/geraldcroes/kotlin_design_patterns"&gt;this GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Don’t hesitate to share your ideas (or your rants, as you wish!) in the comments.&lt;/p&gt;





</description>
      <category>kotlin</category>
      <category>designpatterns</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Don’t Use Design Patterns!</title>
      <dc:creator>geraldcroes</dc:creator>
      <pubDate>Tue, 05 Dec 2017 17:42:25 +0000</pubDate>
      <link>https://dev.to/geraldcroes/dont-use-design-patterns-8pn</link>
      <guid>https://dev.to/geraldcroes/dont-use-design-patterns-8pn</guid>
      <description>

&lt;p&gt;&lt;strong&gt;Don’t Use Design Patterns, but Know Them — Master Them!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KdVm0KzJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AMETwQ-SE2TaENAP6Ix6G7A.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KdVm0KzJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AMETwQ-SE2TaENAP6Ix6G7A.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Behind this catchy title (sorry) lies one of my dearest pieces of advice, nurtured by unfortunate experiences with enthusiastic developers that had just learned about patterns after a training session. How many times have I reviewed lines of code littered with useless classes and cluttered with pointless abstractions? I don’t want to know. (And I don't want to know how many times I was the culprit.)&lt;/p&gt;

&lt;p&gt;Never, never try to put design patterns in practice. Never try to include them into the design of your new application. Don’t engage in aggressive refactoring to add patterns in any existing code for the sake of “making it look better,” or for the sake of flexibility, “so the code will be easier to update in the future.”&lt;/p&gt;

&lt;p&gt;However, study them, understand them, re-read them, think about them and give them some attention.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Metaphor Game
&lt;/h3&gt;

&lt;h4&gt;
  
  
  If I Were a Pianist
&lt;/h4&gt;

&lt;p&gt;Design patterns would be my scales. Scales develop finger nimbleness and train the spirit. Pianists have to know them, but scales aren’t music.&lt;/p&gt;

&lt;p&gt;Imagine the surprise of the audience if, during a performance in a trendy auditorium, they read in the program, “Major scales played on a 3-beat rhythm followed by a playful syncopated minor scales inventory.”&lt;/p&gt;

&lt;p&gt;Similarly, if a composer went through the Moonlight Sonata to refactor the piece by inserting a bland C# scale to ease the cramps of the interpreter’s fingers ... that would be the most terrible answer to a non-existent problem.&lt;/p&gt;

&lt;h4&gt;
  
  
  If I Were a Chess Player
&lt;/h4&gt;

&lt;p&gt;Design patterns would be the problems I solve scanning the newspapers, magazines or dedicated books: These puzzles highlight tactical aspects of the game such as deflection, pin, decoy, passed pawns, sacrifice, overloading … but they aren’t the game, they are just a tool that helps me learn a subset of chess. I couldn’t become a grand champion if I only studied tactics.&lt;/p&gt;

&lt;p&gt;Of course, being a great tactician helps. Knowing tactics helps you find solutions you’d otherwise be oblivious to. But if all I tried to do during my games were to sacrifice my pieces for no reason beyond the fact that it is a tactical aspect of the game (and yet one of the most brilliant ones), I’d end up being a terrible chess player — and nobody would call my style &lt;a href="https://en.wikipedia.org/wiki/Romantic_chess"&gt;romantic&lt;/a&gt;, just plain dumb.&lt;/p&gt;

&lt;h3&gt;
  
  
  No More Metaphors
&lt;/h3&gt;

&lt;p&gt;Design patterns are fantastic when correctly put into practice. They help us when they are an additional source of inspiration but not a destination, not an end.&lt;/p&gt;

&lt;p&gt;Design patterns let developers discuss possible solutions to common problems. They demonstrate simple study cases that are easy to understand and easy to put into practice into more substantial project, into real life designs. Put together, they form architecture catalogs that will welcome beginners and experts alike. They train us on specific and diverse aspects of object-oriented programming.&lt;/p&gt;

&lt;p&gt;Each pattern ought to be used if and only if it fits the problem at hand. Not keeping this in mind will make our code sick and we’ll soon see known diseases such as “Singleton-aches,” along with “OnlyTheFormerDeveloperKnowsAboutThisObfuscatedCode.”&lt;/p&gt;

&lt;p&gt;A pattern is not a defined and immutable solution. A pattern is by no means an implementation. It explains how to overcome common hurdles we'll find on our path. &lt;/p&gt;

&lt;p&gt;Don’t let patterns guide you. Don’t seek to transform your problem so it fits your pet pattern, or you’ll end up writing mediocre solutions to problems you didn’t even have.&lt;/p&gt;

&lt;h3&gt;
  
  
  KISS — Keep It Simple, Stupid.
&lt;/h3&gt;

&lt;p&gt;The most elegant solution is the simplest one, the easiest to understand.&lt;/p&gt;

&lt;p&gt;Not a single “Hello World!” example justifies the use of a pattern, and no “Hello World” example corresponds to a user need. Hello World might even have become a pattern in itself — its sole intent being, "to give a glimpse of a new technology to developers." But no one teaches developers a new technology exclusively using, “Hello World!”&lt;/p&gt;

&lt;p&gt;If a problem has two solutions, one that fits in ten lines of code, and another one with hundreds of lines of code along with a pattern, please consider not using the pattern. Their presence isn’t a quality measurement.&lt;/p&gt;

&lt;p&gt;Of course, if your program is littered with the same ten lines scattered around, it might be time to reconsider.&lt;/p&gt;

&lt;h3&gt;
  
  
  But if …
&lt;/h3&gt;

&lt;p&gt;Never develop for “if something happens … ” Develop because of your current problem. Developing for a blurry hypothetical future is the best way to transform a two-day project into a two-month project. If you happen to justify the presence of a pattern in your code only through a “you know, if … ”, then remove the pattern.&lt;/p&gt;





</description>
      <category>programming</category>
      <category>codingstyle</category>
      <category>opinion</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>REST 101</title>
      <dc:creator>geraldcroes</dc:creator>
      <pubDate>Sun, 03 Dec 2017 11:45:10 +0000</pubDate>
      <link>https://dev.to/geraldcroes/rest-101-5374</link>
      <guid>https://dev.to/geraldcroes/rest-101-5374</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2UkSmy0e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2At7bs-0ZSctf8TI5Y08iOGg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2UkSmy0e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2At7bs-0ZSctf8TI5Y08iOGg.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There was a time when REST was a revolution. The premise of a new world where SOAP problems would be washed away. (I went on a slippery road with that play on words, didn’t I?) REST is now a defacto standard that is starting to lose its momentum (or maybe has already lost a lot of it). For some of us, it still holds a particular place in our mind, our first true love. This journey when we discovered interoperability that worked. For others, starting out in development, it represents a standard that doesn’t belong to the vanguard anymore, something from the past, a legacy, something they don’t want to invest their time in — it’s just there.&lt;/p&gt;

&lt;p&gt;Yes, there are other solutions today aside from web services in REST and JSON, lots of them. There are even multiple REST comprehensions out there, and I already know that by writing this article, I might trigger a nerd war about what is an authentic REST architecture. People will start to raise Roy Fielding’s 2000 dissertation as proof. And to be honest, I’ve done my share of fighting over such ideas, but that time has passed. After having worked for so many years in the industry, I consider myself as just a developer, a regular developer. So, I won’t pretend that I write the truth. I’ll just write what I’ve done and seen for the past years, in practice, at work, out there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REST 101&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I needed to explain REST to my relatives in just one sentence, I’d say, “It’s a way of making applications talk together,” no more, no less. If I wanted to go further (knowing I’d lost them in the process), I’d add, “It’s a way of structuring the dialogue between multiple applications.” Just like an orchestra conductor expects the first violin to be on his left and the cello to be on his right; as a developer, you expect a REST architecture to follow some guidelines to find what you’re looking for quickly.&lt;/p&gt;

&lt;p&gt;When you write an application, your goal is to solve your user’s problem, whether they’re bored (so you write games), overwhelmed (so you write reminders, calendars, to-do lists), creative (well, you got the idea), and so on. There are times when the application itself will have its own problems to solve (for example, getting the GPS coordinates from an address). There are other times when the application will be able to solve other applications’ problems (for example, you’ve written a a grammar checker, a word count, a dictionary or a thesaurus). So at one point or another, you might want your application to ask for a service from another one, or you might entice another application to get its answers from yours. There are many methods at your disposal to enable the communication between two different (and distant) applications, and there are even books dedicated to this matter. REST is one of them.&lt;/p&gt;

&lt;p&gt;REST is a combination of technologies and standards put together. When we say REST, we often have in mind the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP,&lt;/li&gt;
&lt;li&gt;JSON,&lt;/li&gt;
&lt;li&gt;And… that’s it!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Could have been worse right?&lt;/p&gt;

&lt;p&gt;So at its root, that’s all REST is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP, this thing everyone uses&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I tell my friends (well, those who don’t work in IT) that they use an HTTP client almost every day, and that they even have a favorite one, they are often incredulous.&lt;/p&gt;

&lt;p&gt;“Yeah, sure, I have a preference for this whatever client you’re talking about.” And they’re often shocked when they realize that they &lt;em&gt;do&lt;/em&gt; have a preference because a regular web browser &lt;em&gt;is&lt;/em&gt; an HTTP client. What also amazes them (even more) is what’s going on under the hood, when I show them that they can consult the code behind the pages. This internet browser is an HTTP client whose sole purpose is to transform HTML, CSS and Javascript into beautiful pages (or just pages if I were the designer).&lt;/p&gt;

&lt;p&gt;So, in a way, everyone knows about web services — Your machine (the client) talks to another machine (the server) using HTTP (the protocol), so the server sends HTML (the response) displayed in your browser window (the feature of your application).&lt;/p&gt;

&lt;p&gt;Yes, REST uses the exact same protocol as your browser. But before we talk about the differences, let’s talk about the response itself…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON, a humanly readable message&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When computers exchange information, they don’t expect humans to read their raw dialogue. This assumption has its advantages because the human brain is not capable of understanding binary files. Surprisingly, this fantastic non-artificial intelligence that is our brain cannot interpret the message if it’s not expressed using chains of characters (how primary). But humans, these stubborn beings, sometimes find it convenient to be able to read the exchange, and JSON is a text format that humans (even beginners) can understand. It’s also one of the most easily readable ones.&lt;/p&gt;

&lt;p&gt;Let’s say I have access to a web service available at &lt;em&gt;/service/reservations&lt;/em&gt; where I can see the reservations made to my favorite restaurant.&lt;/p&gt;

&lt;p&gt;The response should contain the reservation dates, times, and numbers. And it’s precisely what you would find in a typical JSON response.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;If you told me that only IT professionals were able to understand this JSON response, I’d be surprised…or I would know that you partied too hard yesterday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that’s it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, that’s truly the core of REST — HTTP and JSON. But have we talked about everything yet? Not even close. So let’s keep diving into the subject.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, web services…what can I do with them?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s go back to the purpose. When a user, through an application, deals with a system, it’s either for querying for its current state, or for updating its current state. You can think hard and try to find different use cases, but you won’t (ok, you won’t, if you agree with me that computing a value falls into the category of querying for the current state that is the knowledge).&lt;/p&gt;

&lt;p&gt;Let’s now have a closer look at HTTP. For now, all we did was agree on the fact that your browser was an HTTP client. We’ve also agreed that this browser was dedicated to requesting for the server’s content (the internet). If I was browsing Wikipedia, I could consult a wide variety of pages, answering an even wider variety of questions — what a computer is, what temperature I can expect in Paris in December, who Superman is and what the Matrix is (even if we might not have the full answer for this one). The response would be expressed in natural language and designed with HTML / CSS.&lt;/p&gt;

&lt;p&gt;But what if I wanted to contribute? What if I wanted to add my own piece of knowledge to the system? I’d look for a button to switch to editing mode. I’d fix a typo, add a bit of information (something reliable, like that “Superman is the strongest super-hero, no discussion”), add a reference, or rephrase something I found tricky to understand. Once done, I’d want to send it to Wikipedia, and my browser would use the same HTTP protocol to communicate with the server, but would use a different verb.&lt;/p&gt;

&lt;h3&gt;
  
  
  The HTTP Grammar
&lt;/h3&gt;

&lt;p&gt;Yes, verbs.&lt;/p&gt;

&lt;p&gt;Let’s go back to our restaurant and our reservations. Up to this point, what we’ve done is query the system state — What are the known reservations? To send our request, we’ve used our browser. The browser used HTTP and the verb “GET.” (Like, “GET this information for me,” quite easy to remember.)&lt;/p&gt;

&lt;p&gt;As we saw before, we’ll also need to update the system, like adding a reservation, changing the time or number of guests for a given reservation, or simply deleting our reservation.&lt;/p&gt;

&lt;p&gt;And REST does have the corresponding verbs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;POST: Create a resource,&lt;/li&gt;
&lt;li&gt;PUT: Update a resource,&lt;/li&gt;
&lt;li&gt;DELETE: Delete a resource,&lt;/li&gt;
&lt;li&gt;PATCH: Update properties of a resource,&lt;/li&gt;
&lt;li&gt;GET: Read a resource.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But before we can see them in action, we need to talk about the last piece of the puzzle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow the path&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the verb determines the action, the path (the URL) defines the subject. When we GET &lt;em&gt;/service/reservations&lt;/em&gt;, we deal with the whole reservation collection. As a consequence, if we wanted to add a reservation, we would POST to that same URL (the collection) along with a JSON message representing the new reservation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Request&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;POST /service/reservations&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the following sent data&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;If we consulted the collection right after the insertion, we would get&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Request&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GET /service/reservations&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Response&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Note that the system has added reservation IDs to the collection items.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A single element&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But what if we’d like to get a specific element in that collection? Like, the &lt;em&gt;R3&lt;/em&gt; reservation we’ve just made?&lt;/p&gt;

&lt;p&gt;We would specify the element ID, right at the end of the path, like below.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Request&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GET /service/reservations/R3&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Response&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Notice that the response is now a single element (starts with the opening curling brace), and no longer a collection of elements (that started with the opening bracket).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We haven’t talked about updating a record?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, let’s do this.&lt;/p&gt;

&lt;p&gt;To update a record, we have two choices at our disposal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PUT (to update the whole document)&lt;/li&gt;
&lt;li&gt;PATCH (to update some information)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s start by updating the whole record. The request will look like the one we sent for the creation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Request&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PUT /service/reservations/R3&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;Now, let’s suppose we only want to change one of the properties of our reservation. We’ll use the PATCH verb on the same record (same path). When using PATCH, we can send a partial JSON message. Here is what we’d send to change the time we’d like to arrive.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Request&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PATCH /service/reservations/R3&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Sent data&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;  &lt;/div&gt;

&lt;p&gt;With this record, the time of the reservation will be updated, but the rest of the data will stay untouched.&lt;/p&gt;

&lt;h3&gt;
  
  
  And one verb to delete them
&lt;/h3&gt;

&lt;p&gt;And last, to cancel our reservation (deleting it), we’d do&lt;/p&gt;

&lt;p&gt;&lt;em&gt;#Request&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;DELETE /service/reservations/R3&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is your first stop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So we’ve gone through the core concepts of a REST architecture. If you’re new to development, a project manager, a business analyst or anyone that has to be in touch with IT but not involved in the development and not involved in fine-grained conceptions of those kinds of services, it should be sufficient knowledge to understand people modeling such architectures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Recap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can define REST as a way to enable communication between systems. It stands on HTTP and (for the most part) JSON. We expose services through resources that describe the content of the system thanks to meaningful URLs (collections &lt;em&gt;/resources/&lt;/em&gt;, or individual elements &lt;em&gt;/resources/element-id&lt;/em&gt;). To manipulate the system, the client uses HTTP verbs on these resources so it can CRUD them (Create, Read, Update and Delete).&lt;/p&gt;

&lt;p&gt;If you have any questions, please don’t hesitate to ask in the comments, I’ll do my best to answer. Also, don’t forget that this is the first in a more extended series, and we’ll soon dive deeper into the world of REST!&lt;/p&gt;





</description>
      <category>rest</category>
      <category>webservices</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
