<?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: Gunnar Gissel</title>
    <description>The latest articles on DEV Community by Gunnar Gissel (@monknomo).</description>
    <link>https://dev.to/monknomo</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%2F13239%2Fc83d1bba-2f0e-401c-a419-f13571388fa8.png</url>
      <title>DEV Community: Gunnar Gissel</title>
      <link>https://dev.to/monknomo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/monknomo"/>
    <language>en</language>
    <item>
      <title>New Web Framework?</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Mon, 10 Sep 2018 22:14:48 +0000</pubDate>
      <link>https://dev.to/monknomo/new-web-framework-1n3d</link>
      <guid>https://dev.to/monknomo/new-web-framework-1n3d</guid>
      <description>&lt;p&gt;I've been working on a web framework, but before I go any further, I thought I should check to see if anyone else is interested in the type of framework I'm building.&lt;/p&gt;

&lt;p&gt;Web developers build all kinds of things, but one of the most common things they build are forms.  Order forms.  Email signup forms.  Business process forms.  Forms to enter data from a fax.  All kinds of forms.&lt;/p&gt;

&lt;p&gt;These kind of webapps usually have some html, a custom webservice, some middleware to do business/database stuff and a database.&lt;/p&gt;

&lt;p&gt;I know I get tired of writing the webservice and the middleware boiler plate again and again.  The forms change a little, and you need to either write a fresh webservice and fresh data access objects, or make your existing webservices even smarter.&lt;/p&gt;

&lt;p&gt;What if there was a tool that could inspect your html pages and generate a backend for you?&lt;/p&gt;

&lt;p&gt;I think something could inspect a form, make sensible default table and column names and web services to populate them.  Done right, the tool could make something that would require very little manual tweaking.  I think a tool like this would let web developers put time into what they care about (delivery quality products and making money) as well as what the customers care about (having good looking web page that do what they want).&lt;/p&gt;

&lt;p&gt;Would anyone else be interested in a tool like this?&lt;/p&gt;

</description>
      <category>ask</category>
      <category>webdev</category>
      <category>html</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What is `map` in a Java Stream</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Wed, 13 Jun 2018 23:35:50 +0000</pubDate>
      <link>https://dev.to/monknomo/what-is-map-in-a-java-stream-8j</link>
      <guid>https://dev.to/monknomo/what-is-map-in-a-java-stream-8j</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://www.gunnargissel.com/map-in-java-stream.html"&gt;Originally published at www.gunnargissel.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Mapping is how to convert one type of object to another with a stream.  Say you have a set of &lt;code&gt;Fruit&lt;/code&gt; and you want to show people what is in your set.  It would be helpful to have a list of fruit names to do so.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fruitList.stream().map(fruit::getName).collect(Collectors.toList);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That's pretty simple; you can imagine how to do that in real life with a basket of fruit.  &lt;/p&gt;

&lt;p&gt;Pick up a piece of fruit, write its name down.  Pick up another piece of fruit, write its name down, etc.&lt;/p&gt;

&lt;p&gt;Mapping also lets you you can't easily simulate in real life.  Say you have a Fruit set and you want Oranges, instead of Apples (I think this is closer to transmutation than swapping, but it's a metaphor, ymmv).&lt;/p&gt;

&lt;p&gt;You can do that, with Java:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fruitList.stream().map(fruit -&amp;gt; {
    if( fruit instanceof Apple){
        return new Orange();
    }
    return  fruit;
}).collect(Collectors.toSet);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;If you liked this article, &lt;a href="https://www.gunnargissel.com/pages/email-signup-1.html"&gt;sign up for my mailing list to get monthly updates on interesting programming articles&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>functional</category>
      <category>java8</category>
    </item>
    <item>
      <title>Filter Null Values from a List with Java8 Lambda</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Fri, 08 Jun 2018 23:03:18 +0000</pubDate>
      <link>https://dev.to/monknomo/filter-null-values-from-a-list-with-java8-lambda-351h</link>
      <guid>https://dev.to/monknomo/filter-null-values-from-a-list-with-java8-lambda-351h</guid>
      <description>&lt;p&gt;A common task with Java streams is to clean up the input data so later steps can work without thinking too hard.  Likely the #1 most common cleanup step is to remove nulls from a Collection.&lt;/p&gt;

&lt;p&gt;Streams make it easy:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myCollection.stream()
  .filter(Objects::nonNull)
  .do.what.you.need
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Compare with the classic approaches:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while(myCollection.remove(null));
// do what you need, but you better not need that original list, because it's gone...
myCollection.removeAll(Collections.singleton(null));
// do what you need, but you better not need that original list, because it's gone...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Like the stream approach, these are short and sweet, but unlike the stream approach they modify the original list.  The first example is also pretty slow.&lt;/p&gt;

&lt;p&gt;I like the stream approach because I can chain additional tasks after the filter task, including &lt;code&gt;map&lt;/code&gt;. &lt;code&gt;sorted&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt; and more!.  I find the traditional imperative iterative approach to be not only wordier, but conceptually harder to follow.&lt;/p&gt;

</description>
      <category>java</category>
      <category>functional</category>
      <category>java8</category>
    </item>
    <item>
      <title>Make an Immutable Object - in Java</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Tue, 05 Jun 2018 00:19:53 +0000</pubDate>
      <link>https://dev.to/monknomo/make-an-immutable-object---in-java-480n</link>
      <guid>https://dev.to/monknomo/make-an-immutable-object---in-java-480n</guid>
      <description>&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://www.gunnargissel.com/make-an-immutable-object-in-java.html" rel="noopener noreferrer"&gt;Originally published on www.gunnargissel.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Immutable objects are objects that don't change.  You make them, then you can't change them.  Instead, if you want to change an immutable object, you must clone it and change the clone while you are creating it.&lt;/p&gt;

&lt;p&gt;A Java immutable object must have all its fields be internal, &lt;code&gt;private final&lt;/code&gt; fields.  It must not implement any setters.  It needs a constructor that takes a value for every single field.&lt;/p&gt;

&lt;p&gt;Immutable objects come in handy in multi-threaded environments and in streams.  It is great to rely on objects not changing mid-stream.  Bugs caused by a thread changing another thread's object are often subtle and are very, &lt;em&gt;very&lt;/em&gt; hard to track down.  Immutable objects stop these whole class of problems in their tracks.&lt;/p&gt;

&lt;p&gt;You don't have to take my word for it - see what &lt;a href="https://www.yegor256.com/2014/06/09/objects-should-be-immutable.html" rel="noopener noreferrer"&gt;experts&lt;/a&gt; &lt;a href="http://www.codebetter.com/patricksmacchia/2008/01/13/immutable-types-understand-them-and-use-them/" rel="noopener noreferrer"&gt;around&lt;/a&gt; &lt;a href="http://www.codebetter.com/patricksmacchia/2008/01/13/immutable-types-understand-them-and-use-them/" rel="noopener noreferrer"&gt;the&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/214714/mutable-vs-immutable-objects" rel="noopener noreferrer"&gt;web&lt;/a&gt; say.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Making an Immutable Object&lt;/li&gt;
&lt;li&gt;
Common gotchas

&lt;ol&gt;
&lt;li&gt;Primitives&lt;/li&gt;
&lt;li&gt;Collections&lt;/li&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;li&gt;Objects&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

How to Change an Immutable Object

&lt;ol&gt;
&lt;li&gt;Where to put Builders?&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Handling Bad Data in Immutable Objects&lt;/li&gt;

&lt;li&gt;Wrapup&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Gotchas!&lt;a&gt;&lt;/a&gt;
&lt;/h2&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%2Fi.imgur.com%2F51q4QPRl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F51q4QPRl.jpg" title="a lonely tree on a rock" alt="a lonely tree on a rock" width="426" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lists, arrays, maps, sets and other non-immutable objects can be surprising.  A &lt;code&gt;private final&lt;/code&gt; object with no setter is fixed to the object it was initially assigned, but the values inside that object aren't fixed (unless the object is immutable).&lt;/p&gt;

&lt;p&gt;That means you might have an &lt;code&gt;ImmutableShoppingList myShoppingList = new ImmutableShoppingList(new String[] {"apples","anchovies","pasta"})&lt;/code&gt; and expect that the shopping list will always have "apples", "anchovies" and "pasta".&lt;/p&gt;

&lt;p&gt;Someone could call &lt;code&gt;myShoppingList.getList()[0] = "candy bars";&lt;/code&gt; and change your list to be "candy bars", "anchovies" and "pasta", which is unhealthy and clearly not what you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Primitives &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Good news!  Primitives are immutable, so you don't have to do anything special. &lt;/p&gt;

&lt;h3&gt;
  
  
  Collections &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Good news! &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html" rel="noopener noreferrer"&gt;java.util.Collections&lt;/a&gt; provides a number of convenience methods that make converting a Collection to an UnmodifiableCollection a snap.&lt;/p&gt;

&lt;p&gt;Check out:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Collections.unmodifiableCollection
Collections.unmodifiableList
Collections.unmodifiableMap
Collections.unmodifiableNavigableMap
Collections.unmodifiableNavigableSet
Collections.unmodifiableSet
Collections.unmodifiableSortedMap
Collections.unmodifiableSortedSet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I suggest you store the fields as generic Collections (List, rather than ArrayList), and make the unmodifiable in the constructor, like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ImmutableShoppingList {

    private final List&amp;lt;String&amp;gt; list;

    public ImmutableShoppingList(List&amp;lt;String&amp;gt; list){
        this.list = Collections.unmodifiableList(list);
    }

    public List&amp;lt;String&amp;gt; getList(){
        return list;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This allows you to use IDE code generation to make the getters, which is nice, and contains all the input modifiers in one place, which is also nice.&lt;/p&gt;

&lt;p&gt;Bad news! If you hang onto the reference to the collection when you create the collection, you can still modify it, even if you store it as an unmodifiable collection internally.  Here's an example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;String&amp;gt; originalList = new ArrayList&amp;lt;&amp;gt;();
theList.add("apple");
ImmutableShoppingList blah = new ImmutableShoppingList(originalList);
originalList.add("candy bar");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The supposedly immutable shopping list started with an apple, and had a candy bar added to it after creation.  What can we do about this?&lt;/p&gt;

&lt;p&gt;Clone the list!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ImmutableShoppingList {

    private final List&amp;lt;String&amp;gt; list;

    public ImmutableShoppingList(List&amp;lt;String&amp;gt; list){
        List&amp;lt;String&amp;gt; tmpListOfHolding = new ArrayList&amp;lt;&amp;gt;();
        tmpListOfHolding.addAll(list);
        this.list = Collections.unmodifiableList(tmpListOfHolding);
    }

    public String[] getList(){
        return (String[]) list.toArray();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When we create the immutable object, we deep clone the collection, which severs the connection to the original reference.  Now when we run the "sneak a candy bar in" example, "candy bar" gets added to &lt;code&gt;originalList&lt;/code&gt;, but not the &lt;code&gt;ImmutableShoppingList&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arrays &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Bad news!  Java doesn't have any convenient methods to prevent arrays from being modified.  Your best bet is to either hide the original array and always return a clone, or to not use arrays in the underlying implementation and instead convert a Collection object to an array.&lt;/p&gt;

&lt;p&gt;I prefer to stick with Collections, but if you must have an array in your object's api, this is the approach I would take:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ImmutableShoppingList {

    private final List&amp;lt;String&amp;gt; list;

    public ImmutableShoppingList(String[] list){
        this.list = Collections.unmodifiableList(Arrays.asList(list));
    }

    public String[] getList(){
        return (String[]) list.toArray();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Objects &lt;a href="object-gotchas"&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Object fields can be easy.  If the sub-objects are also immutable, good news!  You don't have to do anything special.&lt;/p&gt;

&lt;p&gt;If the sub-objects are not immutable, they are a lot like a collection.  You need to deep clone them, or the original reference can change your supposedly immutable data out from under your feet.&lt;/p&gt;

&lt;p&gt;Often, you end up working with pre-existing mutable objects, either in your codebase, or in libraries.  In this case, I like to create an immutable object wrapper class that &lt;em&gt;extends&lt;/em&gt; the mutable class.  I find a static &lt;code&gt;getInstance(MutableObject obj)&lt;/code&gt; method can be helpful, but a constructor &lt;code&gt;ImmutableObject(MutableObject obj)&lt;/code&gt; is also a useful thing to have.&lt;/p&gt;
&lt;h2&gt;
  
  
  What About When I Want To Change An Immutable Object? &lt;a&gt;&lt;/a&gt;
&lt;/h2&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%2Fi.imgur.com%2FIHsv75ol.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FIHsv75ol.jpg" title="a woman having a good time in a shop" alt="a woman having a good time in a shop" width="640" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It happens to everyone.  You need an an object, but you don't know everything about the object.  You can't quite commit to an immutable object.&lt;/p&gt;

&lt;p&gt;In this case, I reach for the builder pattern.&lt;/p&gt;

&lt;p&gt;The builder pattern creates a temporary object with the same fields as the desired object.  It has getters and setters for all the fields.  It also has a &lt;code&gt;build()&lt;/code&gt; method that creates the desired object&lt;/p&gt;

&lt;p&gt;Imagine a small immutable object:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ImmutableDog {
    private final String name;
    private final int weight

    public ImmutableDog(String name, int weight){
        this.name = name;
        this.weight = weight;
    }

    public String getName(){
        return this.name;
    }

    public int getWeight(){
        return this.weight;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here's what the builder would look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ImmutableDogBuilder {
    private String name;
    private int weight;

    public ImmutableDogBuilder(){}

    public ImmutableDog build(){
        return new ImmutableDog(name, weight);
    }

    public ImmutableDogBuilder setName(String name){
        this.name = name;
        return this;
    }

    public ImmutableDogBuilder setWeight(int weight){
        this.weight = weight;
        return this;
    }

    public String getName(){
        return this.name;
    }

    public int getWeight(){
        return this.weight;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note the setters&lt;/strong&gt;  I really like this pattern of returning &lt;code&gt;this&lt;/code&gt; on each setters in builder classes, because it creates a very fluent api.  You could use this &lt;code&gt;ImmutableDogBuilder&lt;/code&gt; like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ImmutableDogBuilder dogBuilder = new ImmutableDogBuilder().setName("Rover").setWeight(25);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can imagine in classes with more fields that this compacts your code a lot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where To Put The Builder? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There are two schools of thought here.&lt;/p&gt;

&lt;p&gt;On the one hand, you can create a separate class for the builder.  This is easy, it is very conventional, and your IDE will probably group the classes together, because they probably have similar names.&lt;/p&gt;

&lt;p&gt;On the other hand, you can embed the builder class in the immutable object class as a public static inner class.&lt;/p&gt;

&lt;p&gt;I prefer to embed builder classes in immutable objects, because I view the builder as a helper for the immutable object, and not a standalone thing.  It keeps them together and tightly coupled.&lt;/p&gt;

&lt;h2&gt;
  
  
  What About Immutable Objects With Bad Data? &lt;a&gt;&lt;/a&gt;
&lt;/h2&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%2Fi.imgur.com%2FcqrtgTXl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FcqrtgTXl.jpg" title="a very dirty car" alt="a very dirty car" width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It happens to everybody, especially if you accept input.  Bad data!&lt;/p&gt;

&lt;p&gt;Bad data is no good, but &lt;em&gt;immutable&lt;/em&gt; bad data seems especially wrong - you can't even fix it!&lt;/p&gt;

&lt;p&gt;I use two approaches to prevent bad data from getting turned into immutable objects.&lt;/p&gt;

&lt;p&gt;My primary approach is a suite of business rules that test for sane, permissible data.  The business rules look at builders, and if the builder passes, I deem it ok to create the immutable object.&lt;/p&gt;

&lt;p&gt;My secondary approach is to embed a small amount of business logic in the immutable object.  I don't allow required fields to be null, and any nullable field is an &lt;code&gt;Optional&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ImmutableDog {
    private final String name;
    private final Optional&amp;lt;int&amp;gt; weight

    public ImmutableDog(String name, Optional&amp;lt;int&amp;gt; weight){
        Objects.requireNonNull(name);
        this.name = name;
        this.weight = weight;
    }

    public String getName(){
        return this.name;
    }

    public Optional&amp;lt;int&amp;gt; getWeight(){
        return this.weight;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is an &lt;code&gt;ImmutableDog&lt;/code&gt; that requires a name, but does not require a weight.  It's important to know what to call a dog, but it's not strictly necessary to know that Fluffy weighs 15 lbs.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Objects.requireNonNull&lt;/code&gt; will immediately throw a &lt;code&gt;NullPointerException&lt;/code&gt; if a name is not provided.  This prevents the creation of a nonsensical immutable object.  It also allows users of the immutable object (such as streams or functions) to skip handling nulls.  There are no nulls here.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;Optional&amp;lt;int&amp;gt;&lt;/code&gt; makes consumers of &lt;code&gt;ImmutableDog&lt;/code&gt; immediately aware that they may have to handle a null.  Providing the &lt;code&gt;Optional&lt;/code&gt; api gives downstream users an easy, functional way of handling nulls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapup &lt;a&gt;&lt;/a&gt;
&lt;/h2&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%2Fi.imgur.com%2FfiWbSvbl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FfiWbSvbl.jpg" title="a colorful celebration" alt="a colorful celebration" width="640" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Immutable objects require some special care and handling, but their utility is worth it.&lt;/p&gt;

&lt;p&gt;The main principles to keep in mind are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone arrays, Collections and Objects internal to your immutable object&lt;/li&gt;
&lt;li&gt;Use builders when you need a mutable object&lt;/li&gt;
&lt;li&gt;Use Optional to indicate nullable fields in your object's api&lt;/li&gt;
&lt;li&gt;Fail fast on bad data - Objects.requireNonNull can help&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Go forth, and stop mutating&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://www.gunnargissel.com/pages/email-signup-1.html" rel="noopener noreferrer"&gt;You've read this far, subscribe to my mailing list for more of the same.  It's once a month, you can unsubscribe any time, and I promise not to spam you.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>functional</category>
      <category>design</category>
      <category>tips</category>
    </item>
    <item>
      <title>Host a React App with Dropwizard</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Thu, 31 May 2018 13:52:38 +0000</pubDate>
      <link>https://dev.to/monknomo/host-a-react-app-with-dropwizard-3lik</link>
      <guid>https://dev.to/monknomo/host-a-react-app-with-dropwizard-3lik</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://www.gunnargissel.com/host-a-react-app-with-dropwizard.html" rel="noopener noreferrer"&gt;Originally post on www.gunnargissel.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dropwizard is a great Java framework for building RESTful applications.  It helps you quickly set up a server with a RESTful api, and has lots of useful features right out of the box for making production-grade apps.&lt;/p&gt;

&lt;p&gt;React is a great Javascript library for building webapps.  Via create-react-app, React comes with excellent tools for running a development server and creating a production build.  The create-react-app production build makes a directory full of static html and Javascript files.  You could host these with Apache, or nginx, or any variety of webservers.  &lt;/p&gt;

&lt;p&gt;It is convenient to minimize the number of pieces of infrastructure an application requires, so hosting the static files with the api server is appealing.  The standard way to host static files with Dropwizard is to include them in the jar, so they are accessible from the classpath.  There is no way to externally host static assets out of the box.&lt;/p&gt;

&lt;p&gt;Fortunately, some kind souls created the &lt;a href="https://github.com/dropwizard-bundles/dropwizard-configurable-assets-bundle" rel="noopener noreferrer"&gt;Dropwizard Configurable Asset Bundle&lt;/a&gt; which allows you to configure an external directory to be hosted at a uri by Dropwizard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&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%2Fi.imgur.com%2FHqQpL3Tm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FHqQpL3Tm.jpg" alt="origami wizard's duel" title="origami wizard's duel" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've created a &lt;a href="https://github.com/monknomo/gravina-dropwizard-configurable-assets-bundle-skeleton" rel="noopener noreferrer"&gt;skeletal Dropwizard echo server&lt;/a&gt; and a &lt;a href="https://github.com/monknomo/gravina-react-ui" rel="noopener noreferrer"&gt;teeny-tiny React app&lt;/a&gt; to go with it.  The Dropwizard server is a plain vanilla configuration except for the addition of this dependency in the &lt;code&gt;pom.xml&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;io.dropwizard-bundles&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;dropwizard-configurable-assets-bundle&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.2.2&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and this addition in the &lt;code&gt;app.yml&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assets:
  mappings:
    /assets: /
  overrides:
    /: /teeny-tiny-react-app/build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and this change to the configuration class:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... extends Configuration implements AssetsBundleConfiguration {
...
@Override
public AssetsConfiguration getAssetsConfiguration() { return assets; }
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and this addition to the app initialization:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bootstrap.addBundle(new ConfiguredAssetsBundle("/assets/", "/", "index.html"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and finally, this addition to the app run command:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env.jersey().setUrlPattern("/api/*")&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  But What Does It Mean?&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;These configuration changes add the dropwizard-configurable-assets-bundle to your project, assign the &lt;code&gt;/assets&lt;/code&gt; classpath to the &lt;code&gt;/&lt;/code&gt; uri, and the &lt;code&gt;/&lt;/code&gt; uri to the &lt;code&gt;/teeny-tiny-react-app/build&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;They also include a setting that makes Dropwizard look for index.html if nothing matches the incoming uri.&lt;/p&gt;

&lt;p&gt;Finally, they host the Dropwizard resources at &lt;code&gt;/api/*&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do I Use It?
&lt;/h2&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%2Fi.imgur.com%2F8ZPzPx1m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F8ZPzPx1m.jpg" alt="bulldozer" title="bulldozer" width="320" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This configuration allows for two usage modes - development and production.&lt;/p&gt;

&lt;p&gt;In development mode, proceed as normal.  Fire up Dropwizard &lt;code&gt;java -jar muh-sweet-rest-api.jar server app.yml&lt;/code&gt; then move over to your React dev environment and start coding while running &lt;code&gt;npm run start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In production mode, fire up Dropwizard, and then do a React build &lt;code&gt;npm run build&lt;/code&gt;.  This will create a production-optimized build of your React app, which you can place where Dropwizard expects to find it.&lt;/p&gt;

&lt;p&gt;You'll have two options to view your React app - the default &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; or Dropwizard-served &lt;a href="http://localhost:8085" rel="noopener noreferrer"&gt;http://localhost:8085&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default port is hosted by React's built in server and has all the auto-reloading goodies you are used to.&lt;/p&gt;

&lt;p&gt;Dropwizard's port hosts a static build, so it doesn't auto-reload as you code.  It will, however, automatically serve new code if you manually deploy it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should I do this?
&lt;/h2&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%2Fi.imgur.com%2FiWsnVTrm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FiWsnVTrm.jpg" alt="girl on slide" title="girl on slide" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should do this if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are already running a Java backend&lt;/li&gt;
&lt;li&gt;You want to deploy React changes separately from Java changes&lt;/li&gt;
&lt;li&gt;You have an ops team that will let you touch the war deploy location, but not the html deploy location (or vice-versa)&lt;/li&gt;
&lt;li&gt;Messing with proxying is difficult (environment specific)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should not do this if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want the frontend and the backend in lockstep&lt;/li&gt;
&lt;li&gt;Proxying is easy&lt;/li&gt;
&lt;li&gt;You already have one or two html servers&lt;/li&gt;
&lt;li&gt;You don't want to use Java&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you liked this article, &lt;a href="https://www.gunnargissel.com/pages/email-signup-1.html" rel="noopener noreferrer"&gt;sign up for my mailing list to get monthly updates on interesting programming articles&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/malachus/" rel="noopener noreferrer"&gt;Malachi Brown&lt;/a&gt; for the picture of the &lt;a href="https://flic.kr/p/483B5i" rel="noopener noreferrer"&gt;wizard's duel&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/magilla03/" rel="noopener noreferrer"&gt;David McGregor&lt;/a&gt; for the picture of the &lt;a href="https://flic.kr/p/c1H69U" rel="noopener noreferrer"&gt;water droplet&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/wbaiv/" rel="noopener noreferrer"&gt;Bill Abbot&lt;/a&gt; for the picture of the &lt;a href="https://flic.kr/p/bz7oMC" rel="noopener noreferrer"&gt;bulldozer&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/bobandmel/" rel="noopener noreferrer"&gt;Mel Johnson&lt;/a&gt; for the picture of the &lt;a href="https://flic.kr/p/7s8bR3" rel="noopener noreferrer"&gt;kid on the slide&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>What's your Developer Story?</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Tue, 22 May 2018 16:44:41 +0000</pubDate>
      <link>https://dev.to/monknomo/whats-your-developer-story-47me</link>
      <guid>https://dev.to/monknomo/whats-your-developer-story-47me</guid>
      <description>&lt;p&gt;Howdy dev.to peeps!  &lt;/p&gt;

&lt;p&gt;I'm curious what your stories are - how did you start, where are you now and what did it take to get from point A to point B?  Extra points for gory details about the journey&lt;/p&gt;

&lt;p&gt;I'd love to hear from people at all points in the path, from folks just starting out to people who've been on it longer than I've been alive.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>Taking Notes</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Wed, 16 May 2018 04:04:22 +0000</pubDate>
      <link>https://dev.to/monknomo/taking-notes-3b35</link>
      <guid>https://dev.to/monknomo/taking-notes-3b35</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gunnargissel.com/taking-notes.html" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="http://www.gunnargissel.com" rel="noopener noreferrer"&gt;www.gunnargissel.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is longer than the usual &lt;a href="https://dev.to/t/discuss"&gt;#discuss&lt;/a&gt; post, but I'd love to hear about how dev.to takes their notes.  What systems do you all use?  Who does it all with a computer, and how do they handle meeting notes?  Who has some paper-based system I've never heard of?  I'm pretty curious what y'all up to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes!
&lt;/h2&gt;

&lt;p&gt;I wrote earlier about &lt;a href="https://www.gunnargissel.com/protect-yourself-like-the-fbi--with-memos.html" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;em&gt;why&lt;/em&gt; you might take notes.  Here's &lt;em&gt;how&lt;/em&gt; I take notes:&lt;/p&gt;

&lt;p&gt;I've tried a lot of systems.  I've tried Evernote.  I've tried a wiki (several wikis, really).  I've tried text files on the filesystem.  I've tried Google Drive.  None of these systems worked for me.  Their organizational schemes, and the fact that I need a working computer to use them puts too many barriers between me, and the notes I want to write.&lt;/p&gt;

&lt;p&gt;The note taking system that works best of me is &lt;a href="https://bulletjournal.com/get-started/" rel="noopener noreferrer"&gt;Bullet Journaling,&lt;/a&gt; which is a structured way of categorizing and organizing notes.  The practices that I find most useful are adopting a set of shorthand symbols for each note, keeping a weekly log, keeping a monthly calendar and keeping an index of my notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Take Notes
&lt;/h2&gt;

&lt;p&gt;I take notes at all the meetings and trainings I attend.  Sometimes my notes are just "I attended this meeting".  Other times, I come out with a list of todos, and still other times I just come out with a bunch of things I want to remember.&lt;/p&gt;

&lt;p&gt;Here's an example of notes I took during a project management training:&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%2Fi.imgur.com%2FWmf0qm0l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWmf0qm0l.jpg" alt="An example of what notes look like in a bullet journal" title="An example of what notes look like in a bullet journal" width="480" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I kept track of what the training was about and observations on &lt;a href="https://en.wikipedia.org/wiki/The_Flight_of_the_Phoenix_%281965_film%29" rel="noopener noreferrer"&gt;The Flight of the Phoenix,&lt;/a&gt; a training aid our instructor chose.  I didn't have any todos or other particularly notable notes on this page, but it gives a flavor of how I use bullet journaling in the day to day.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Preferred Set of Symbols
&lt;/h3&gt;

&lt;p&gt;I adopted a set of symbols based on the bullet journal suggestions to indicate different types of notes.  I went with a subset of the bullet journal symbols, because I found my todos are generally not very complicated.  They either need to happen, happened or aren't going to happen.  I didn't find moving them around from day to day very useful.&lt;/p&gt;

&lt;h4&gt;
  
  
  -
&lt;/h4&gt;

&lt;p&gt;I use a dash to prefix general notes and observations&lt;/p&gt;

&lt;h4&gt;
  
  
  ⚪
&lt;/h4&gt;

&lt;p&gt;I use an open circle to indicate a todo.  I put an "X" through the circle when it's done or cross it out when it becomes irrelevant.&lt;/p&gt;

&lt;h4&gt;
  
  
  👀
&lt;/h4&gt;

&lt;p&gt;I use an eyeball for things I want to look into more&lt;/p&gt;

&lt;h4&gt;
  
  
  !
&lt;/h4&gt;

&lt;p&gt;I use an exclamation point for things that I think are important&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping a Weekly Log
&lt;/h2&gt;

&lt;p&gt;I work in an office environment, with semi-annual performance reviews.  I find writing up what I did over the last six months a lot easier if I've kept track of it at some kind of high level overview.  To that end, I use weekly logs&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%2Fi.imgur.com%2FDzf5Lkkl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FDzf5Lkkl.jpg" alt="A detailed log of my weekly activities" width="480" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I write out the log at the start of the week, then as I do things, I put a short note in on each day.  "Attended stakeholder meeting," "Wrote workflow container," "Created permit entry UI," "Mentored junior developer," etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping a Monthly Log
&lt;/h2&gt;

&lt;p&gt;The weekly logs are great for looking back, but sometimes I want to look forward.  I keep a couple months calendar in my journal to help plan when my busy periods are likely to be.&lt;/p&gt;

&lt;p&gt;Here's what a fairly empty calendar on a new month looks 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%2Fi.imgur.com%2F9Z8SaNKl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F9Z8SaNKl.jpg" alt="An empty calendar for a new month" title="An empty calendar for a new month" width="480" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I learn new things, I put important events in my calendar, whether they are target release dates, testing cycles or demos.  I also use these calendars to plan around personal events, like vacations or doctor appointments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping an Index
&lt;/h2&gt;

&lt;p&gt;Keeping an index sounds boring and difficult, but I find that if I'm diligent, it's not particularly difficult, and it turns out to be one of the most useful parts of my journal.&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%2Fimgur.com%2FaasPfDal.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FaasPfDal.jpg" alt="An index of topics my work bullet journal covers" title="An index of topics my work bullet journal covers" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The three practices that make keeping an index easy are&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Number pages as you turn to them&lt;/li&gt;
&lt;li&gt;Title new entries before you write them&lt;/li&gt;
&lt;li&gt;Update the index as soon as you create a new entry&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The payoff is six months after you've written a bunch and can't quite remember where that important technical decision originates from.  Just look at the project meetings, or other promising entries and cut your search time down!&lt;/p&gt;

&lt;h2&gt;
  
  
  Ride off into the Sunset
&lt;/h2&gt;

&lt;p&gt;Whatever method you choose to take notes in, having a system makes it easier to use the notes after writing them.  I find the Bullet Journal technique very useful, but it took me a couple tries to settle in on how I wanted to record information.  I'm still learning and changing how I take notes - never hurts to change!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.gunnargissel.com/" rel="noopener noreferrer"&gt;If you like what you read here, consider visiting my blog for more!&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Credits
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/furryscalyman/" rel="noopener noreferrer"&gt;Matt Reinbold&lt;/a&gt; for the &lt;a href="https://flic.kr/p/yWtvF" rel="noopener noreferrer"&gt;notepad&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>management</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Protect Yourself like the FBI — with Memos</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Wed, 28 Mar 2018 03:59:17 +0000</pubDate>
      <link>https://dev.to/monknomo/protect-yourself-like-the-fbi--with-memos-mkc</link>
      <guid>https://dev.to/monknomo/protect-yourself-like-the-fbi--with-memos-mkc</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gunnargissel.com/protect-yourself-like-the-fbi--with-memos.html" rel="noopener noreferrer"&gt;www.gunnargissel.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Donald Trump has been in the news a lot lately.  Especially concerning FBI investigations and memos.  It seems like everyone in Washington is fighting with memos - &lt;a href="https://www.theatlantic.com/politics/archive/2017/05/congress-reacts-to-comey-memo-report/526947/" rel="noopener noreferrer"&gt;Comey&lt;/a&gt;, &lt;a href="https://www.politico.com/story/2018/03/17/mccabe-memo-trump-fbi-469097" rel="noopener noreferrer"&gt;McCabe&lt;/a&gt;, &lt;a href="https://www.theatlantic.com/politics/archive/2018/02/read-the-full-text-of-the-nunes-memo/552191/" rel="noopener noreferrer"&gt;Nunes&lt;/a&gt; - &lt;a href="https://news.google.com/news/search/section/q/trump%20memo/trump%20memo?hl=en&amp;amp;gl=US&amp;amp;ned=us" rel="noopener noreferrer"&gt;the list goes on and on&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Clearly memos are important, but they also seem distant and removed from programming.  You programmers reading this article aren't in a fight with the president &lt;em&gt;or&lt;/em&gt; the FBI&lt;sup id="fnr-footnotes-1"&gt;1&lt;/sup&gt;, so why should you care about memos?&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools of Bureaucracy
&lt;/h2&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%2Fi.imgur.com%2FvNIG4jwm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FvNIG4jwm.jpg" alt="Printing out memos" title="A printer with stack of memos on it" width="320" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should care about memos because we work in a fundamentally bureaucratic society run by managers&lt;sup id="fnr-footnotes-2"&gt;2&lt;/sup&gt;.  It's likely that you work for an organization that is large enough to have its own bureaucracy - most programmers do.  &lt;/p&gt;

&lt;p&gt;If you aren't sure whether you work in a bureaucracy, here's a quick test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is there a process for getting hired?
&lt;/li&gt;
&lt;li&gt;Is here a process for leaving the company?&lt;/li&gt;
&lt;li&gt;Is there a process for getting fired?&lt;/li&gt;
&lt;li&gt;Is there a process for getting a promotion?&lt;/li&gt;
&lt;li&gt;Does your boss have a boss?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you answered yes to more than two of them, congratulations!  You are a programmer &lt;em&gt;and&lt;/em&gt; part-time bureaucrat.  &lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Memo?
&lt;/h2&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%2Fi.imgur.com%2FrkYnp3Sm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FrkYnp3Sm.jpg" alt="Write things in a notebook" title="Notebooks, for writing memos" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's common for programmers to understand memos in &lt;a href="https://en.wikipedia.org/wiki/Office_Space" rel="noopener noreferrer"&gt;Office Space&lt;/a&gt; terms.  They are something supervisors do, and they really need TPS coversheets.  While this is true&lt;sup id="fnr-footnotes-3"&gt;3&lt;/sup&gt;, it is a limiting conception of what a memo is.&lt;/p&gt;

&lt;p&gt;Memo is short for "memorandum" which is from the Latin phrase &lt;em&gt;memorandum est,&lt;/em&gt; "It must be remembered that..."  A memo is some kind of documentation that jogs your memory.  Of course, there are many different kinds memos in the modern world - policy memos, memorandum of understandings, meeting minutes, the list goes on.&lt;/p&gt;

&lt;p&gt;From day-to-day programmer, the most important kind of memo is the &lt;a href="http://www.weeklystandard.com/a-brief-history-of-the-memo-to-the-file/article/2008086" rel="noopener noreferrer"&gt;memo-to-file&lt;/a&gt;.  A memo-to-file is something you write after a conversation or an action that describes what happened.  It isn't addressed to anyone, it's not trying to persuade anyone of anything.  A memo-to-file simply records an event as you understood it at a certain point in time.&lt;/p&gt;

&lt;p&gt;Put another way, a memo-to-file is a note with a date on it.  &lt;/p&gt;

&lt;p&gt;You should know that memos are being created about you.  Your manager, coworkers, and stakeholders are all probably writing things down, about stuff you did!&lt;/p&gt;

&lt;p&gt;Hold off on the panic attack.  They probably aren't writing down bad things - the vast majority of memos are neutral.  "&lt;em&gt;Met with so-and-so, discussed project.  Committed to reviewing Jira issues&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;For the most part, these memos go unused.  Written once, read never.  They do, however, come in handy in a variety of situations, usually after something has gone wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concrete Examples
&lt;/h2&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%2Fi.imgur.com%2FLOc9JUfm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLOc9JUfm.jpg" alt="Filing cabinets full of memos" title="Filing cabinets full of memos" width="240" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  On the Road to a Job Hunt
&lt;/h3&gt;

&lt;p&gt;Let's start right off the bat with the grim example.  Your boss is not happy with your performance and thinks they may have to fire you.  In bureaucratic organizations, there is a process connected with firing, and it typically starts with a performance improvement plan&lt;sup id="fnr-footnotes-4"&gt;4&lt;/sup&gt;.  &lt;/p&gt;

&lt;p&gt;Firing is expensive, and it is important to document a repeated pattern of behavior&lt;sup id="fnr-footnotes-5"&gt;5&lt;/sup&gt;.  Because firing is expensive, many bureaucratic organizations recommend supervisors take actions to head off people getting even a performance improvement plan - mentoring meetings, feedback meetings, checkins, etc.  &lt;/p&gt;

&lt;p&gt;Supervisors document these informal actions with memos-to-file.  "&lt;em&gt;Counseled so-and-so that they need to inform stakeholders of a blown deadline before said deadline is blown.&lt;/em&gt;"  These notes build a case of a repeated pattern of behavior that supports the action they take down the road.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reviewing What Went Wrong
&lt;/h3&gt;

&lt;p&gt;A less grim occurrence is the post mortem, or after action report.  A system failed, and the team wants to figure out what happened and why it failed. Keeping notes about who asked you to do what can be helpful when establishing a timeline.  For example, "&lt;em&gt;Chief stakeholder Jane wanted the big feature rolled out next week, so she asked me to do an unscheduled deploy on Friday.&lt;/em&gt;"  &lt;/p&gt;

&lt;p&gt;They can also help establish mindset before a system failure - the best post mortems assume everyone is trying their professional best, so knowing why a person thought the action that caused the failure was a good idea is helpful, and memos-to-file can be a useful resource to determine the "why's".&lt;/p&gt;

&lt;h3&gt;
  
  
  Day-to-Day Disagreements
&lt;/h3&gt;

&lt;p&gt;The most common (and least grim) place that memos-to-file can help a programmer out, is mild disagreement with stakeholders about feature requests and bug fixes.  It's common to walk out of a meeting feeling like you have a shared understanding about what to do next, only to find a week or a month later that you did not.&lt;/p&gt;

&lt;p&gt;A contemporaneous memo of what you understood as you left the meeting is useful, because it can help you figure out where the disagreement started.  They can be useful in figuring out who was 'wrong' but this is of limited usefulness when everyone is on the same team working towards shared goals in a supportive fashion.&lt;/p&gt;

&lt;p&gt;In the event that you are working on a contentious team, this type of memo can be useful protection - "See, I did what they said!  It's not my fault they changed their mind."  Hopefully you are not on a team like this, but even the best teams sometimes veer unexpectedly towards blame and contention.&lt;/p&gt;

&lt;h3&gt;
  
  
  End of the Year Writeups
&lt;/h3&gt;

&lt;p&gt;Everyone with a boss must, from time to time, say what they did and why it was good for the company.  This often comes in the form of an annual performance review with a short write up about what you did and a quick meeting with your boss.  These meetings have a high impact on your promotion and bonus potential.  It is in your best interest to have a good summary of your accomplishments at hand.&lt;/p&gt;

&lt;p&gt;A good collection of memos documenting the people you talked to and the actions you took, as well as the motivations and results, makes quick work of writing end of the year accomplishments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be Prepared
&lt;/h2&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%2Fi.imgur.com%2FYw9ncFkm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FYw9ncFkm.jpg" alt="A hall of filing cabinets" title="A hall of filling cabinets" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Write memos, not with the intention of needing them, but with the knowledge that you might need them as circumstances change.  "Be Prepared" is an excellent motto, whether you are a scout, a backup-conscientious admin or a programmer-bureaucrat.  What is a happy situation today, may turn tomorrow.  Memos-to-file can help bail you out when things turn sour.&lt;/p&gt;

&lt;p&gt;Happy writing!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you liked this and want great articles on programming and leadership delivered to your inbox monthly, &lt;a href="https://www.gunnargissel.com/pages/email-signup-1.html" rel="noopener noreferrer"&gt;sign up for my newsletter!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/rueful/" rel="noopener noreferrer"&gt;Kiran Foster&lt;/a&gt; for the &lt;a href="https://flic.kr/p/a1VxYw" rel="noopener noreferrer"&gt;picture of a filing cabinet&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/mcfarlandmo/" rel="noopener noreferrer"&gt;mcfarlandmo&lt;/a&gt; for the &lt;a href="https://flic.kr/p/5ZrohQ" rel="noopener noreferrer"&gt;picture of many filing cabinets&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/1000points/" rel="noopener noreferrer"&gt;Florian Hufsky&lt;/a&gt; for the &lt;a href="https://flic.kr/p/5AHHMk" rel="noopener noreferrer"&gt;picture of a notebook&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/orinrobertjohn/" rel="noopener noreferrer"&gt;Orin Zebest&lt;/a&gt; for the &lt;a href="https://flic.kr/p/4knuKB" rel="noopener noreferrer"&gt;picture of a paper cliff&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/skolbwilliams/" rel="noopener noreferrer"&gt;No More Plains&lt;/a&gt; for the &lt;a href="https://flic.kr/p/dciy51" rel="noopener noreferrer"&gt;picture of a printer&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;p&gt;&lt;a id="fn-footnotes-1"&gt;1: &lt;/a&gt; Unless you are in a fight with the president and/or the FBI - in that case, I'm interested and want to hear more; &lt;a href="mailto:gunnar@gunnargissel.com"&gt;dish!&lt;/a&gt; ⏎&lt;br&gt;
&lt;a id="fn-footnotes-2"&gt;2: &lt;/a&gt; &lt;a href="https://ebooks.adelaide.edu.au/o/orwell/george/james_burnham/" rel="noopener noreferrer"&gt;Say what you will&lt;/a&gt; about &lt;a href="https://en.wikipedia.org/wiki/James_Burnham" rel="noopener noreferrer"&gt;James Burnham&lt;/a&gt; and &lt;em&gt;&lt;a href="https://www.goodreads.com/book/show/1700735.The_Managerial_Revolution" rel="noopener noreferrer"&gt;The Managerial Revolution&lt;/a&gt;&lt;/em&gt;, I think there is something to the description of society there ⏎&lt;br&gt;
&lt;a id="fn-footnotes-3"&gt;3: &lt;/a&gt;Not really. ⏎&lt;br&gt;
&lt;a id="fn-footnotes-4"&gt;4: &lt;/a&gt;Your organization may call these something else, but the idea is a last chance plan before they show you the door ⏎&lt;br&gt;
&lt;a id="fn-footnotes-5"&gt;5: &lt;/a&gt;For liability and unemployment insurance reasons both ⏎&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>leadership</category>
      <category>workplace</category>
    </item>
    <item>
      <title>Turn Your Spaghetti Code into Functions - Part 3</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Tue, 20 Mar 2018 04:12:42 +0000</pubDate>
      <link>https://dev.to/monknomo/turn-your-spaghetti-code-into-functions---part-3-3dif</link>
      <guid>https://dev.to/monknomo/turn-your-spaghetti-code-into-functions---part-3-3dif</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://www.gunnargissel.com/turn-your-spaghetti-code-into-functions-part-3.html" rel="noopener noreferrer"&gt;Orignally posted at www.gunnargissel.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Picking up &lt;a href="http://www.gunnargissel.com/turn-your-spaghetti-code-into-functions-part-2.html" rel="noopener noreferrer"&gt;where we left off in Part II&lt;/a&gt;, let's set the stage for using a validator.   We left our example elephant in a cool convertible, but let's upgrade his ride to a rocket ship.  We'll start like all good rocket scientists - with a round of cleaning!&lt;/p&gt;

&lt;p&gt;After &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Mise_en_place" rel="noopener noreferrer"&gt;mise en place&lt;/a&gt;&lt;/em&gt;, we will be ready to implement a &lt;code&gt;Validator&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt;, which will create a single, standard, expandable format for business rules and an api for consuming results from business rule queries.  No more guessing what a rule-compliant call looks like!  No more stringing together crystal towers of nested boolean logic!&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;There are a couple places where we used &lt;code&gt;.and()&lt;/code&gt; to combine predicates in an &lt;code&gt;if&lt;/code&gt; block.  Replace those with an independent predicate, so all &lt;code&gt;if&lt;/code&gt; blocks refer to only one predicate&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;static final Predicate&amp;lt;WidgetTransfer&amp;gt; suffientAmount = trans -&amp;gt; trans.getTransferer().getAccount(trans.getFromAccount()).getBalance().compareTo(trans.getAmount()) &amp;lt; 0;
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isPartner = trans -&amp;gt; trans.getTransferTypeCode().equals("200");
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isFriendsAndFamily = trans -&amp;gt; trans.getTransferTypeCode().equals("710");
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isFriendAndFamilyDiscountLegal = trans -&amp;gt; trans.getAreaCode().matches("574|213|363|510");
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isPartneringArea = trans -&amp;gt; trans.getAreaCode().matches("907|412|213");
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isDirigibleForbiddenArea = trans -&amp;gt; trans.getAreaCode().matches("213");
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isDirigibleCategory = trans -&amp;gt; trans.getTransferer().getCategory().equals("D");
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isInternal = trans -&amp;gt; trans.getTypeCode().equals("I");
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isBlockSize = trans -&amp;gt; isBlockSize(trans);
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; isTotalOverCap = trans -&amp;gt; isTotalOverCap(trans);

    static final Predicate&amp;lt;WidgetTransfer&amp;gt; parterTransferReqs = trans -&amp;gt; isPartner.and(isPartneringArea.negate()).test(trans);
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; dirigibleTransferReqs = trans -&amp;gt; isPartner.and(isDirigibleForbiddenArea.negate()).and(isDirigibleCategory).test(trans);
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; friendsAndFamilyReqs = trans -&amp;gt; isFriendsAndFamily.and(isFriendAndFamilyDiscountLegal.negate()).test(trans);
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; internalBlockReqs = trans -&amp;gt; isInternal.and(isBlockSize).test(trans);
    static final Predicate&amp;lt;WidgetTransfer&amp;gt; internalTotalCapReqs = trans -&amp;gt; isInternal.and(isTotalOverCap).test(trans);

    public static final String checkWidgetTransfer(WidgetTransfer transfer) {
        String businessRuleErrors = "";

        if (suffientAmount.test(transfer)) {
            businessRuleErrors += "Insufficient balance to transfer ; ";
        }

        if (parterTransferReqs.test(transfer)) {
            businessRuleErrors += "This area is not a transfer eligible area. ; ";
        }

        if (dirigibleTransferReqs.test(transfer)) {
            businessRuleErrors += "D Category Transferer can only be transferred in transfer area 213. ; ";
        }

        if (friendsAndFamilyReqs.test(transfer)) {
            businessRuleErrors += "This area is not a transfer eligible area. ; ";
        }

        if (internalBlockReqs.test(transfer)) {
            businessRuleErrors += "Amount is too small for I type transfer. ; ";
        }

        if (internalTotalCapReqs.test(transfer)) {
            businessRuleErrors += "This transfer is too large. ; ";
        }

        return businessRuleErrors;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above code has a lot of boiler plate - but it's boiler plate that is invisible to the average Java dev.  All those &lt;code&gt;if&lt;/code&gt; blocks are boiler plate.  You have to type them again, and again.  What if I told you, you could use a validator and clean up all your business rules?  Think of the miles of conditionals in your business code, and imagine each reduced to a single composable function call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boilerplate Removal
&lt;/h2&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%2Fi.imgur.com%2Fz5pXylbl.jpg" 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%2Fi.imgur.com%2Fz5pXylbl.jpg" title="literal boiler plate" alt="literal boiler plat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another problem is that &lt;code&gt;checkWidgetTransfer&lt;/code&gt; returns a string.  This pushes the responsibility for determining if an error has occured onto the calling method.  All &lt;code&gt;checkWidgetTransfer&lt;/code&gt; callers need a section that looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String result = checkWidgetTransfer(transfer);
if(null == result || 0 == result.size()) {
    //continue
}else{
    handleError(result);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Multiply this by every bizarre process that Bob in accounting, Carol in sales uses and Duane in HQ uses.  It can get.... &lt;strong&gt;big.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can save on typing, share conditionals and share business logic by using the &lt;code&gt;Validator&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt; technique.  Here's what it looks like from the caller's perspective:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checkWidgetTransfer(transfer).onError(err -&amp;gt; handleError(err));
//continue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This provides an api for the caller that indicates what an error condition is.  Callers no longer have to guess that an empty string is a pass, and a non-empty string is a fail.  The api provides a place to put error handling, which can take an existing function, or have an on-the-fly lambda in place.  Sweet!&lt;/p&gt;

&lt;p&gt;You still have to write up Bob, Carol and Duane's favorite workflow. but things are compact and you don't have to go down many twisty branches, each more a like than the last. &lt;/p&gt;

&lt;h3&gt;
  
  
  Now with a Validator
&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%2Fi.imgur.com%2FLxHru8gl.jpg" 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%2Fi.imgur.com%2FLxHru8gl.jpg" title="Blastoff!" alt="rocket blasting off"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if you didn't have to write any if/then/else statements?  What if you you only had to write the logic, and something else would handle stringing that logic together.  A validator can make that possible.&lt;/p&gt;

&lt;p&gt;Here's what the implementation of &lt;code&gt;checkWidgetTransfer&lt;/code&gt; looks like, using a validator:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static final Result&amp;lt;WidgetTransfer&amp;gt; checkWidgetTransfer(WidgetTransfer transfer) {
    Validator&amp;lt;WidgetTransfer&amp;gt; widgetTransferValidator = new Validator();
    widgetTransferValidator.addRule(suffientAmount, "Insufficient balance to transfer");
    widgetTransferValidator.addRule(parterTransferReqs, "This area is not a transfer eligible area");
    widgetTransferValidator.addRule(dirigibleTransferReqs, "D Category Transferer can only be transferred in transfer area 213");
    widgetTransferValidator.addRule(friendsAndFamilyReqs, "This area is not an eligible area");
    widgetTransferValidator.addRule(internalBlockReqs, "Amount is too small for I type transfer");
    widgetTransferValidator.addRule(internalTotalCapReqs, "This transfer is too large");
    return widgetTransferValidator.validate(transfer); 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The validator can take as many rules as needed, and each rule gets a name and a matching message.  The validator ensures every rule is applied to the transfer, and a &lt;code&gt;Result&lt;/code&gt; is returned, containing either the error messages or the transfer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation Details
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/monknomo/If-Else-Block-Refactoring/blob/master/src/main/java/com/gunnargissel/suemez/businessrulerefactorexample/refactor5/Validator.java" rel="noopener noreferrer"&gt;I implemented a &lt;code&gt;Validator&lt;/code&gt;&lt;/a&gt; as a &lt;code&gt;HashMap&lt;/code&gt; of functions to error strings.  The &lt;code&gt;validate&lt;/code&gt; method tests each function, and if the test is true, collects the matching message in the &lt;code&gt;Result&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/monknomo/If-Else-Block-Refactoring/blob/master/src/main/java/com/gunnargissel/suemez/businessrulerefactorexample/refactor5/Result.java" rel="noopener noreferrer"&gt;I implemented &lt;code&gt;Result&lt;/code&gt;&lt;/a&gt; as an &lt;code&gt;Either&lt;/code&gt;.  Callers have the option of getting a boolean &lt;code&gt;hasErrors&lt;/code&gt; or passing in a &lt;code&gt;Consumer&lt;/code&gt; to &lt;code&gt;onError&lt;/code&gt;.  The important thing about a &lt;code&gt;Result&lt;/code&gt; is that it is never null and it guides the developer to the correct method of handling an error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;With just a tiny push, we helped our elephant reach orbit.  We've gone from &lt;a href=""&gt;bog standard spaghetti business logic&lt;/a&gt; to pure functions embodying composable business logic.  Thank you for coming along for ride.  I welcome comments or feedback at &lt;a href="mailto:gunnar@gunnargissel.com"&gt;gunnar@gunnargissel.com&lt;/a&gt;, or &lt;a href="https://twitter.com/monknomo" rel="noopener noreferrer"&gt;@monknomo on Twitter&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%2Fi.imgur.com%2F5Xg3VrRl.jpg" 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%2Fi.imgur.com%2F5Xg3VrRl.jpg" alt="elephant in space, happy they have cleaned up code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.gunnargissel.com/pages/email-signup-1.html" rel="noopener noreferrer"&gt;Sign up for my email list to get notifcations about updates in continuing series, and a monthly digest of interesting programming and tech leadership articles&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/oliverdodd/" rel="noopener noreferrer"&gt;Oliver Dodd&lt;/a&gt; for the &lt;a href="https://flic.kr/p/8N681r" rel="noopener noreferrer"&gt;elephant&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thank you &lt;a href="https://www.nasa.gov/multimedia/imagegallery/image_feature_1146.html" rel="noopener noreferrer"&gt;NASA, ESA, N. Smith (U. California, Berkeley) et al., and The Hubble Heritage Team (STScI/AURA)&lt;/a&gt; for the Carina Nebula&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://flic.kr/p/fejqBW" rel="noopener noreferrer"&gt;Photo of the shuttle Endeavour&lt;/a&gt; by &lt;a href="https://www.flickr.com/photos/73577218@N00/" rel="noopener noreferrer"&gt;Mr. Littlehand&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://flic.kr/p/Fvyd" rel="noopener noreferrer"&gt;Boiler Plate&lt;/a&gt; &lt;a href="https://www.flickr.com/photos/elsie/" rel="noopener noreferrer"&gt;from Les Chatfield&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://flic.kr/p/q5sdna" rel="noopener noreferrer"&gt;Blastoff&lt;/a&gt; by &lt;a href="https://www.flickr.com/photos/matthew_lancaster_2/" rel="noopener noreferrer"&gt;Matthew Lancaster&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>functional</category>
    </item>
    <item>
      <title>Java 8 Stream Cheatsheet</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Wed, 28 Feb 2018 18:29:52 +0000</pubDate>
      <link>https://dev.to/monknomo/java-8-stream-cheatsheet--oad</link>
      <guid>https://dev.to/monknomo/java-8-stream-cheatsheet--oad</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://www.gunnargissel.com/java8-stream-cheatsheet.html" rel="noopener noreferrer"&gt;www.gunnargissel.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Streams are a way of working with objects in a collection.&lt;/p&gt;

&lt;p&gt;Streams allow a person to say what they &lt;em&gt;want&lt;/em&gt; to have at the end.  Contrast that with the imperative approach that requires a person to say &lt;em&gt;how&lt;/em&gt; to collect what they want to have at the end.&lt;/p&gt;

&lt;p&gt;Streams also allow for trivial multi-threading.&lt;/p&gt;

&lt;h1&gt;
  
  
  Basic Stream Methods
&lt;/h1&gt;

&lt;p&gt;There are a couple basic methods that govern stream interaction.  The general idea behind these methods is manipulating a collection of objects so that the only objects remaining are the ones you want.&lt;/p&gt;

&lt;p&gt;If I had to pick the indispensable methods for working with a Stream, I'd say &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Filter&lt;/code&gt;, and &lt;code&gt;Collect&lt;/code&gt; are on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filter&lt;/strong&gt;&lt;br&gt;
Filter takes a &lt;code&gt;Predicate&lt;/code&gt;, and leaves only the values that the &lt;code&gt;Predicate&lt;/code&gt; is true for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Map&lt;/strong&gt;&lt;br&gt;
Map takes a &lt;code&gt;Function&lt;/code&gt;, and transforms the values in the stream from one type to another&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sorted&lt;/strong&gt;&lt;br&gt;
Sorted takes a &lt;code&gt;Comparator&lt;/code&gt;, and orders the values in the stream according to the ordering specified in the &lt;code&gt;Comparator&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collect&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;Collect&lt;/code&gt; stops the stream and puts the values from the stream into some kind of &lt;code&gt;Collection&lt;/code&gt;, like a &lt;code&gt;List&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;toArray&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;toArray()&lt;/code&gt; stops the stream and returns an array with the elements contained in the stream.&lt;/p&gt;

&lt;h1&gt;
  
  
  Finders
&lt;/h1&gt;

&lt;p&gt;A common task, when using a collection, is to get an element out of the stream.  These are generally used after &lt;code&gt;Filter&lt;/code&gt; and &lt;code&gt;Map&lt;/code&gt;, to guarantee that the element you find matches some criteria and is of the preferred type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;findAny()&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;findAny()&lt;/code&gt; returns an &lt;code&gt;Optional&lt;/code&gt; containing an element in the stream (or nothing, if the stream is empty).  Order is not respected here, especially in parallel stream situations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;findFirst()&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;findFirst()&lt;/code&gt; returns an &lt;code&gt;Optional&lt;/code&gt; containing the first element in the stream (or nothing, if the stream is empty).  Order is respected when using this method&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;max(Comparator comparator)&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;max&lt;/code&gt; returns the maximum element of the stream for the given &lt;code&gt;Comparator&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;min(Comparator comparator)&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;min&lt;/code&gt; returns the minimum element of the stream for the given &lt;code&gt;Comparator&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Matchers
&lt;/h1&gt;

&lt;p&gt;Another common task is to determine if the objects meet some given criteria.  These "matcher" methods indicate whether some, none or all the objects in a stream meet a given criteria.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;allMatch(Predicate pred)&lt;/strong&gt;&lt;br&gt;
Returns &lt;code&gt;true&lt;/code&gt; if all elements in the stream match the &lt;code&gt;Predicate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;anyMatch(Predicate pred)&lt;/strong&gt;&lt;br&gt;
Returns &lt;code&gt;true&lt;/code&gt; if any elements in the stream match the &lt;code&gt;Predicate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;noneMatch(Predicate pred)&lt;/strong&gt;&lt;br&gt;
Returns &lt;code&gt;true&lt;/code&gt; if no elements in the stream match the &lt;code&gt;Predicate&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Stream Modifiers
&lt;/h1&gt;

&lt;p&gt;From time to time, a stream is not quite the "right" stream.  These methods create a new stream with slightly different characteristics than the old stream, whether it is a different length, different starting point, or a guarantee that only unique objects are contained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;distinct()&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;distinct()&lt;/code&gt; creates a new stream that has only distinct elements (based on &lt;code&gt;.equals&lt;/code&gt;) in it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;limit(int maxSize)&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;limit(maxSize)&lt;/code&gt; creates a new stream by truncating the original stream to be no longer than maxSize.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;skip(long n)&lt;/strong&gt;&lt;br&gt;
Skips the first n elements of the stream, and creates a new stream out of the rest&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sorted()&lt;/strong&gt;&lt;br&gt;
Creates a new stream, where the elements are sorted according to natural order&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sorted(Comparator comparator)&lt;/strong&gt;&lt;br&gt;
Creates a new stream, where the elements are sorted according to the &lt;code&gt;Comparator&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Stream Characterizers
&lt;/h1&gt;

&lt;p&gt;Another common task, when working with collections, is to determine some characteristics about the collection as a whole.  The stream api provides a method to figure out how big a given stream is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;count()&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;count()&lt;/code&gt; counts the number of elements in the stream&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you like this, visit &lt;a href="https://www.gunnargissel.com" rel="noopener noreferrer"&gt;my programming blog&lt;/a&gt; for more tips and tricks&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Thank you &lt;a href="https://www.flickr.com/photos/wickenden/" rel="noopener noreferrer"&gt;Don LaVange&lt;/a&gt; for the picture of a &lt;a href="https://flic.kr/p/5quJsw" rel="noopener noreferrer"&gt;stream&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>functional</category>
      <category>cheatsheet</category>
      <category>devtips</category>
    </item>
    <item>
      <title>Useful Resources and Tools</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Tue, 27 Feb 2018 22:07:07 +0000</pubDate>
      <link>https://dev.to/monknomo/useful-resources-and-tools--33cm</link>
      <guid>https://dev.to/monknomo/useful-resources-and-tools--33cm</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gunnargissel.com/pages/useful-resources-and-tools.html"&gt;www.gunnargissel.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I collect useful resources for software development here - how to do it and tools to do it with&lt;/p&gt;

&lt;p&gt;Expect periodic updates&lt;/p&gt;

&lt;h1&gt;
  
  
  Tools
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Writing Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.hemingwayapp.com/"&gt;Hemingway App&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Hemingway App is a great website (or app!) that helps pare down your writing into direct, adverb-less prose.  I like it as an editing tool, although I take it with a grain of salt because I prefer my writing to be a touch more florid than Hemingway&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://swagger.io/swagger-ui/"&gt;Swagger RESTful API documentation tools&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;If you have a RESTful API, you ought to document it.  Since you're documenting it on the web, why not make the documentation talk to your API?  Swagger makes it easy to write the docs, and it makes the docs incredibly useful by automatically creating a way for readers to interact with your API&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Editors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://atom.io/"&gt;Atom&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Atom is a javascript text editor that works on the web and on the desktop.  It has a ton of plugins and can very nearly hold its own as a full IDE.  I like how you can integrate the command line into Atom, and how its syntax highlighting is pretty good&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://notepad-plus-plus.org/"&gt;Notepad++&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Notepad++ has been an old standby of my Windows development.  It has tabs!  It has multi-cursor editing!  It has rudimentary syntax highlighting!  It opens big files pretty quickly!  It has macros!  What more can you ask for?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Windows Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rapidee.com/en/about"&gt;RapidEE&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;RapidEE makes managing environment variables on Windows a great deal more tolerable.  It shows both system and user environment variables, and most importantly, highlights paths that are broken.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://putty.org/"&gt;putty&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;For the time being, if you want ssh on Windows, putty is the place to go.  Hopefully this changes for future versions of Windows.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://smartty.sysprogs.com/"&gt;smarTTY&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;smarTTY is a friendlier ssh client for Windows.  It allows for tabbed sessions, remembers servers you've connected to, and can handle doing key exchanges automatically.  It can't do everything - if you need to authenticate with a CAC card, you'r stuck with putty.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.7-zip.org/"&gt;7-zip&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;7-zip unzips just about anything&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.cygwin.com/"&gt;Cygwin&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;If you are on Windows, aren't aren't in an organization that lets you use the super sweet Linux subsystem, Cygwin is the next best thing.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chocolatey.org/"&gt;Chocolatey&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Windows' missing package manager.  It brings some of the pizzazz of apt-get or npm to Windows.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Drawing Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://inkscape.org/"&gt;Inkscape&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Vector art tool - sometimes you want an svg, but you don't want to pony up for Illustrator.  Inkscape has your back&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gimp.org/"&gt;Gimp&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Gimp isn't as good as photoshop, but for editing pictures, resizing stuff and photoshopping two images together, it is good enough.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://graphviz.org/"&gt;Graphviz&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Easy graphs!  Not the regular kind of graphs, but the mathematical kind of interrelated nodes.  My main beef is that it doesn't always order the nodes the way I want, but it gets the job done.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Websites
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to"&gt;dev.to&lt;/a&gt; :)

&lt;ul&gt;
&lt;li&gt;dev.to is a great website for general programming articles.  It has an incredibly welcoming community, and &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://news.ycombinator.com"&gt;Hacker News&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Hacker News is so-so on community, IMHO, but is still a very good place to find the big headlines and fads of the tech world&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://lobste.rs"&gt;Lobste.rs&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Lobsters is invite only, very similar to HN, but with a smaller less annoying community&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.indiehackers.com"&gt;IndieHackers&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;IndieHackers is for smalltimers trying to make money on the internet, like me, and maybe you!  They are a very friendly and encouraging community&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.gunnargissel.com/pages/email-signup-1.html"&gt;&lt;strong&gt;Join my mailing list to get useful tools and techniques delivered to your inbox once a month!&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  credits
&lt;/h2&gt;

&lt;p&gt;Thank you &lt;a href="https://www.flickr.com/photos/ndrwfgg/"&gt;Andrew Fogg&lt;/a&gt; for the picture of &lt;a href="https://flic.kr/p/6t59b"&gt;tools&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tools</category>
      <category>utilities</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Newb Valley</title>
      <dc:creator>Gunnar Gissel</dc:creator>
      <pubDate>Thu, 04 Jan 2018 16:56:42 +0000</pubDate>
      <link>https://dev.to/monknomo/newb-valley-lh4</link>
      <guid>https://dev.to/monknomo/newb-valley-lh4</guid>
      <description>&lt;p&gt;There comes a point when you are good at what you do.  If you're like me, you've been pretty good at things for a long time - pretty good at school, pretty good at work, pretty good at structured environments that provide a path and use skills you already know.  This is a very comfortable place to inhabit.  It comes with respect, both self respect, and respect from your peers and colleagues.&lt;/p&gt;

&lt;p&gt;As long as you stay in your structured environment, on the path that uses/improves your existing skills, getting better feels easy - or at least, predictable.  You put in effort, your skills improve in a (more or less) linear fashion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OKReuMF4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ym8uDgGl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OKReuMF4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ym8uDgGl.jpg" title="The mountain you are about to climb"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sooner or later, you may have the desire to learn something outside of your existing expert skillset.  If you're like me, you are surprised when this &lt;em&gt;hurts&lt;/em&gt;.  Suddenly, you are not good at what you are trying to do.  The shock of a drop in your skill level is disconcerting, and the temptation to retreat back to the comfort of your old groove is strong.&lt;/p&gt;

&lt;p&gt;To pick a concrete example, you may be a talented developer.  You can pick up new languages, or build new systems.  If there is something programming-related you don't know, you have a good idea how long it will take to learn it, and how you should go about learning it.&lt;/p&gt;

&lt;p&gt;But one day you become a lead developer, or transition into the management.  Suddenly, you need skills that you &lt;em&gt;haven't&lt;/em&gt; practiced for years and &lt;em&gt;don't&lt;/em&gt; have a clear path from where you are. &lt;/p&gt;

&lt;h2&gt;
  
  
  Welcome to Newb Valley!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1-nVQw7A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/7QJZMYAl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1-nVQw7A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/7QJZMYAl.jpg" title="A graph with your expected rate of progression, versus your actual rate of progression"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's the difference between your hoped for path and your actual path that causes a lot of pain.  There are a couple things you can do to reduce your pain and power through Newb Valley&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Know it is coming&lt;/li&gt;
&lt;li&gt;Have a plan to bridge the gap&lt;/li&gt;
&lt;li&gt;Forgive yourself for mistakes&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Know it is Coming
&lt;/h3&gt;

&lt;p&gt;This is an easy, but critical step.  If your new found lack of competence surprises you, the impulse to pack it in and retreat to comfort may prove overwhelming.  Instead, lean in to your newb-ness.  Embrace your lack of competence - after all, if you knew what to do, you wouldn't be learning.&lt;/p&gt;

&lt;p&gt;Developing a level of comfort with uncomfortable situations will go far.&lt;/p&gt;

&lt;h3&gt;
  
  
  Have a Plan
&lt;/h3&gt;

&lt;p&gt;One way of developing and keeping comfort in the face of uncomfortable situations is to have a plan to lean on.  You know you're in for an uphill struggle, so figure out in advance how you want to climb that hill.  Give yourself some smaller goals and ways to check on your progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Forgive Yourself
&lt;/h3&gt;

&lt;p&gt;You will be less competent for some amount of time.&lt;/p&gt;

&lt;p&gt;That means you'll make mistakes.  You'll blow deadlines.  You'll deliver less scope than you had planned.  Your plan to progress to the next level will be wrong.&lt;/p&gt;

&lt;p&gt;Take a breath, re-evaluate, learn a lesson and move on.&lt;/p&gt;

&lt;p&gt;You'll climb out of Newb Valley before you know it&lt;/p&gt;

&lt;h2&gt;
  
  
  Visit My Blog
&lt;/h2&gt;

&lt;p&gt;If you liked this, &lt;a href="https://www.gunnargissel.com"&gt;visit my blog&lt;/a&gt; for more great articles on the intersection of leadership and programming.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.gunnargissel.com/pages/email-signup-1.html"&gt;Please sign up for my email list for a monthly digest of interesting programming and tech leadership articles&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/sandybrownjensen/"&gt;Sandy Brown Jensen&lt;/a&gt; for the picture of &lt;a href="https://flic.kr/p/oY5rrt"&gt;the mountain climbers&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thank you &lt;a href="https://www.flickr.com/photos/briantaylor/"&gt;Brian Taylor&lt;/a&gt; for the picture of &lt;a href="https://flic.kr/p/qP7esU"&gt;"Newb Valley"&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>leadership</category>
      <category>diagram</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
