<?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: Jason McCreary</title>
    <description>The latest articles on DEV Community by Jason McCreary (@gonedark).</description>
    <link>https://dev.to/gonedark</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%2F1695%2Fef6452f0-7835-4e3c-8b0e-d58fcc44229d.jpg</url>
      <title>DEV Community: Jason McCreary</title>
      <link>https://dev.to/gonedark</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gonedark"/>
    <language>en</language>
    <item>
      <title>42 Git Questions Answered</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Thu, 17 Oct 2019 15:07:01 +0000</pubDate>
      <link>https://dev.to/gonedark/42-git-questions-answered-3npa</link>
      <guid>https://dev.to/gonedark/42-git-questions-answered-3npa</guid>
      <description>&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;What is your favorite Git command?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I am a sucker for &lt;code&gt;git add -p&lt;/code&gt;. This adds changes in "patch mode" which is a built-in command line program. It iterates over each of my changes and asks me if I want to stage them?&lt;/p&gt;

&lt;p&gt;This command forces me to &lt;strong&gt;slow down and review my changes&lt;/strong&gt;. Too often as developers we rush this part thinking the work is done. I can't tell you how many times I've run &lt;code&gt;git add .&lt;/code&gt; in a hurry to later realize I committed "scratch" files or debug statements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Why do you prefer using Git from the command line?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As developers, we're already using the command line for so many other things. Why not for Git as well?&lt;/p&gt;

&lt;p&gt;In addition, Git has a very small command set. One that is pretty easy to learn as a developer and will improve your development workflow by using it directly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can we use &lt;code&gt;stage&lt;/code&gt; command?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;stage&lt;/code&gt; is a built-in alias for &lt;code&gt;add&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can I save the changes in a branch and checkout to other branch?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So you may use &lt;code&gt;git stash&lt;/code&gt; to temporarily store your changes or make a WIP commit. The goal is to have a clean working index.&lt;/p&gt;

&lt;p&gt;Personally, I prefer working with WIP commits rather than &lt;code&gt;stash&lt;/code&gt;. I find them easier to reference and potentially share.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When should I use &lt;code&gt;git stash&lt;/code&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I like to use &lt;code&gt;stash&lt;/code&gt; for quickly getting the "working index" &lt;strong&gt;clean&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How do I see how to use a Git command?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the &lt;code&gt;--help&lt;/code&gt; option for any command. Example, &lt;code&gt;git stash --help&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What is "git flow"?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;git flow is a &lt;a href="https://nvie.com/posts/a-successful-git-branching-model/"&gt;branching strategy&lt;/a&gt; using multiple "long-lived" branches which mirror the software development lifecycle. Changes are merged between these branches as work is needed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What is "GitHub Flow"?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Basically GitHub Flow is a branded name for a &lt;code&gt;master&lt;/code&gt;/feature branch workflow. GitHub has formalized this into a process using their toolset shown in this &lt;a href="https://guides.github.com"&gt;visual tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Which branching strategy do you prefer?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I've worked on hundreds of Git projects and I will say most reach for "git flow". Only a a handful of these projects ever &lt;em&gt;needed&lt;/em&gt; that strategy. Often because it was versioned software.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;master&lt;/code&gt;/feature branching strategy is much easier to manage, especially when you're just starting out. And it's very easy to switch to "git flow" if needed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What was the &lt;code&gt;git open&lt;/code&gt; command you used?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's a separate command and available as an &lt;a href="https://www.npmjs.com/package/git-open"&gt;npm package&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can you reset a branch when there are files that were added in other branch but still appear as untracked or modified in your working branch?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is often the result of switch branches when the "working index" is &lt;strong&gt;unclean&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There's no built in way to correct this with Git. I normally avoid this by ensuring my prompt has a "status" indicator and running commands like &lt;code&gt;git status&lt;/code&gt; anytime I change a branch.&lt;/p&gt;

&lt;p&gt;These habits give me an opportunity to catch this early so I can either &lt;code&gt;stash&lt;/code&gt; or &lt;code&gt;commit&lt;/code&gt; those changes working on a new branch.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can I rename a branch ?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;git branch -m current-branch-name new-branch-name&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How I can use &lt;code&gt;cherry-pick&lt;/code&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;git cherry-pick [reference]&lt;/code&gt;. Remember this is a &lt;strong&gt;reapplying&lt;/strong&gt; command, so it will change the commit SHA.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If I make a revert from a branch and (for example &lt;code&gt;HEAD~3&lt;/code&gt;), is it possible to go back to &lt;code&gt;HEAD&lt;/code&gt; again (like a recovery of your last updates?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this scenario, I would immediately undo the &lt;code&gt;revert&lt;/code&gt; commit (which is the &lt;code&gt;HEAD&lt;/code&gt; commit) by running &lt;code&gt;git reset --hard HEAD~1&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When use &lt;code&gt;git pull&lt;/code&gt; and &lt;code&gt;git fetch&lt;/code&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;git pull&lt;/code&gt; will &lt;strong&gt;download&lt;/strong&gt; the commits to your current branch. Remember, &lt;code&gt;git pull&lt;/code&gt; is really the combination of the &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;merge&lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git fetch&lt;/code&gt; will &lt;strong&gt;retrieve&lt;/strong&gt; the latest references from a remote.&lt;/p&gt;

&lt;p&gt;A good analogy is with a podcast player or email client. You might retrieve the latest podcasts or emails (fetch), but you haven't actually downloaded the podcast or email attachments locally yet (pull).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Why sometimes we need use &lt;code&gt;--force&lt;/code&gt; to push the changes of a rebase?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;rebase&lt;/code&gt; is a command which may &lt;strong&gt;reapply&lt;/strong&gt; commits which changes their SHA1 hash. If so, the local commit history will no longer align with its remote branch.&lt;/p&gt;

&lt;p&gt;When this happens you will get a &lt;strong&gt;rejected&lt;/strong&gt; &lt;code&gt;push&lt;/code&gt;. &lt;strong&gt;Only when rejected&lt;/strong&gt; should you consider using &lt;code&gt;git push --force&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Doing so will overwrite the remote commit history with your local commit history. So always slow down and &lt;strong&gt;think about why&lt;/strong&gt; you need to use &lt;code&gt;--force&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Can you use a branch to merge multiple branches and then send this branch to master?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Absolutely. It's common under most of the Git workflows for branches to accumulate changes from multiple other branches. Ultimately these branches are "promoted" into the main branch.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Should I do a rebase from a very old branch?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Only if you have to.&lt;/p&gt;

&lt;p&gt;Depending on your workflow, it may be possible to merge a stale branch into your main branch.&lt;/p&gt;

&lt;p&gt;If you need to bring a branch up-to-date, I prefer &lt;code&gt;rebase&lt;/code&gt;. It provides a cleaner history of only your changes instead of commits from other branches or merges.&lt;/p&gt;

&lt;p&gt;However, while always possible, using &lt;code&gt;rebase&lt;/code&gt; may be a painful process since each of your commits are reapplied. This may lead to multiple conflicts. If so, I normally &lt;code&gt;--abort&lt;/code&gt; the &lt;code&gt;rebase&lt;/code&gt; and use &lt;code&gt;merge&lt;/code&gt; instead to resolve all the conflicts once.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When using &lt;code&gt;rebase -i&lt;/code&gt;, what's the difference between &lt;code&gt;squash&lt;/code&gt; and &lt;code&gt;fixup&lt;/code&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Both &lt;code&gt;squash&lt;/code&gt; and &lt;code&gt;fixup&lt;/code&gt; combine two commits. &lt;code&gt;squash&lt;/code&gt; pauses the rebase process and allows you to adjust their commit message. &lt;code&gt;fixup&lt;/code&gt; automatically uses the message from the first commit.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Often when I &lt;code&gt;rebase&lt;/code&gt; my feature branch with &lt;code&gt;master&lt;/code&gt;, for each commit I need resolve conflicts?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes. Since the changes from each commit is &lt;strong&gt;reapplied&lt;/strong&gt; during &lt;code&gt;rebase&lt;/code&gt;, you have to resolve any conflicts as they happen.&lt;/p&gt;

&lt;p&gt;This means a commit conflicts early in the process, or if you resolve it incorrectly, it's likely many of the following commits will conflict as well.&lt;/p&gt;

&lt;p&gt;To limit this, I often use &lt;code&gt;rebase -i&lt;/code&gt; to first condense my commit history so it is easier to work with.&lt;/p&gt;

&lt;p&gt;If there are still conflicts across many commits, I may use &lt;code&gt;merge&lt;/code&gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is necessary update my branch with master before merge it with master?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Depending on your workflow, it may be possible to merge a stale branch into your main branch.&lt;/p&gt;

&lt;p&gt;If your workflow uses "fast-forward" only merges, then it will be necessary to update your branch before merging.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do you recommend use GitKraken?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I am an advocate for using Git from the command line. I find this keeps me in full control of managing changes, as using commands to improve my development process.&lt;/p&gt;

&lt;p&gt;Of course, certain visual actions like managing branches and viewing file differences will always be better in a GUI. Personally, I find viewing such things in the browser during the merge process to be enough.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Could you do an &lt;code&gt;--amend&lt;/code&gt; of a commit when it already was pushed?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes. However, you would not want to amend a commit after it is merged into another branch since &lt;code&gt;--amend&lt;/code&gt; changes the commit.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When I know I will work on something for a while, should I open a &lt;em&gt;pull request&lt;/em&gt; for each change or a complete pull request for all the work?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You normally want to open a pull request for all the work.&lt;/p&gt;

&lt;p&gt;However, if you are working on something for a long time. It might be beneficial to merge smaller changes along the way. Doing so will prevent dependencies on your branch or staleness.&lt;/p&gt;

&lt;p&gt;This will depend on the type of changes you are making.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is it good practice make a &lt;code&gt;release&lt;/code&gt; branch before merge a branch to &lt;code&gt;master&lt;/code&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This depends heavily on your deployment process. Creating a &lt;code&gt;release&lt;/code&gt; branch can be beneficial to group together work from multiple branches and test them as a whole before merging them into your main branch.&lt;/p&gt;

&lt;p&gt;Since the source branches remain separate and unmerged, you will have more flexibility in the final merge.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How to take just some commits from &lt;code&gt;master&lt;/code&gt;? Let's say I don't want to take the last commit but do a rebase.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Assuming &lt;code&gt;master&lt;/code&gt; is your main branch, you don't want to selectively pull commits from its history. This will cause conflicts later.&lt;/p&gt;

&lt;p&gt;You will want to &lt;code&gt;merge&lt;/code&gt; or &lt;code&gt;rebase&lt;/code&gt; your branch will all the changes from master.&lt;/p&gt;

&lt;p&gt;For pulling select commits from a branch other than your main branch, you can use &lt;code&gt;git cherry-pick&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Are there some special themes that I can set up on my terminal?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I cover &lt;a href="https://gettinggit.com/everyday-git/terminal-tweaks-for-git"&gt;configuring and customizing your terminal&lt;/a&gt; in Getting Git.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Which option is best instead of use the command &lt;code&gt;git push --force&lt;/code&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There really isn't an alternative to &lt;code&gt;git push --force&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that said, if you properly update your branch with &lt;code&gt;merge&lt;/code&gt; or &lt;code&gt;rebase&lt;/code&gt; you should not need to use &lt;code&gt;git push --force&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Only when you have run commands which change your local commit history from the history you previously shared should &lt;code&gt;git push --force&lt;/code&gt; be required.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When I select &lt;code&gt;drop&lt;/code&gt; during &lt;code&gt;git rebase -&lt;/code&gt;, is the code related to that commit deleted?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes!&lt;/p&gt;

&lt;p&gt;To revive this code, you will need to find a state prior to the &lt;code&gt;rebase&lt;/code&gt; from the &lt;code&gt;reflog&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can we track automatically a remote branch?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Normally branch tracking is set up automatically by Git when you &lt;code&gt;checkout&lt;/code&gt; or create a branch.&lt;/p&gt;

&lt;p&gt;If not, you can update this the next time you push with: &lt;code&gt;git push -u remote-name branch-name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Or you can set it explicitly with:&lt;code&gt;git branch --set-upstream-to=remote-name/branch-name&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is a best practice &lt;code&gt;rebase&lt;/code&gt; a branch before updating it?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I believe so, simply for the reason organizing or collapsing your commits with &lt;code&gt;git rebase -i&lt;/code&gt; first gives you more context during the update process.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is there a way to split a commit into more commits (something inverse to &lt;code&gt;fixup&lt;/code&gt;/&lt;code&gt;squash&lt;/code&gt;)?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You could use the &lt;code&gt;exec&lt;/code&gt; command during the &lt;code&gt;rebase -i&lt;/code&gt; process to attempt to modify the working index and split up changes.&lt;/p&gt;

&lt;p&gt;You can also use &lt;code&gt;git reset&lt;/code&gt; to undo recent commits and place their changes in the working index to then separate their changes into new commits.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is there a way to go or see a commit that was fixed up?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Not the previous commits. You can using &lt;code&gt;git show&lt;/code&gt; to see the changes within the new commit?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What does &lt;code&gt;rebase --skip&lt;/code&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This tells &lt;code&gt;rebase&lt;/code&gt; to not apply the current changes during the rebase process.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How can I remove remote branches?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can remove a remote branch by pushing "nothing" with:&lt;br&gt;
&lt;code&gt;git push origin :branch-name-to-remove&lt;/code&gt; or using the &lt;code&gt;-d&lt;/code&gt; option with: &lt;code&gt;git push -d origin some-other-branch-2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To remove local reference to remote branches, you can run: &lt;code&gt;git remote prune origin&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What's the difference between &lt;code&gt;checkout&lt;/code&gt; and &lt;code&gt;reset&lt;/code&gt;?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Both of these commands can be used to undo changes. &lt;code&gt;checkout&lt;/code&gt; is arguably more robust as it allows you to not only undo current changes, but also undo a set of changes by retrieving an older version of a file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reset&lt;/code&gt;, by default, works more with changing the state of changes within the working index. As such, it really only deals with the current changes.&lt;/p&gt;

&lt;p&gt;I prefer &lt;code&gt;reset&lt;/code&gt;. The wording makes more sense for the action, which is often to change the state or discard current changes. I tend to reserve &lt;code&gt;checkout&lt;/code&gt; for switching branches and the rare occasion of restoring an old version of a file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What commands should I avoid using in normal workflow?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Anything that could be destructive to your history, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git push origin master -f&lt;/code&gt; (NEVER)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git revert&lt;/code&gt; (on a feature branch)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git cherry-pick&lt;/code&gt; (changes from &lt;code&gt;master&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Under a normal workflow, I try to avoid using &lt;code&gt;git merge&lt;/code&gt; directly as this is often built into the process through pull requests.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If I have a branch (B) that points to other branch (A) and I have another branch (C) which needs code from (A) and (B) and master which process must follow to have (C) updated?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Interesting. This depends on a few things…&lt;/p&gt;

&lt;p&gt;Are &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; something that can be merged into &lt;code&gt;master&lt;/code&gt;? If so, you could merge &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; into &lt;code&gt;master&lt;/code&gt;, and then update &lt;code&gt;C&lt;/code&gt; with the latest changes from &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If not, you may be able to simply merge &lt;code&gt;B&lt;/code&gt; into &lt;code&gt;C&lt;/code&gt; since it contains the changes from &lt;code&gt;A&lt;/code&gt; already.&lt;/p&gt;

&lt;p&gt;In the extreme case, you could merge &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;master&lt;/code&gt; into &lt;code&gt;C&lt;/code&gt;. However, it's likely the order of merging would matter to avoid conflicts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What are some of the aliases you use?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I &lt;a href="https://jasonmccreary.me/articles/stop-aliasing-core-git-commands/"&gt;don't alias Git commands&lt;/a&gt; often. Especially not core commands. I find doing so creates confusion, especially as a trainer.&lt;/p&gt;

&lt;p&gt;With that said, I do have a few aliases for common commands or commands I use with a lot of options:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;alias.unstage reset HEAD &lt;span class="nt"&gt;--&lt;/span&gt;
alias.append commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;--no-edit&lt;/span&gt;
alias.wip commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"WIP"&lt;/span&gt;
alias.logo log &lt;span class="nt"&gt;--oneline&lt;/span&gt;
alias.lola log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--decorate&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;What are some lesser known Git commands?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;git bisect&lt;/code&gt; is a life-saver for finding an existing bug in the code. While I've only used it a few times, it has been impressively precise and saved hours of looking for a needle in a haystack.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git archive&lt;/code&gt; is another nice one for packaging up a set of changes. This can be helpful for sharing work with a third-party or mico-deployments.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git reflog&lt;/code&gt; is probably known, but worth mentioning as it provides a nice way to "undo" commands when things go wrong.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Can you recommend some books for learning more about Git?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sure. I recommend reading at least the first 3 chapters of &lt;a href="https://git-scm.com/book/en/v2"&gt;Pro Git&lt;/a&gt;. I have done so a few times over the years and always learn something.&lt;/p&gt;

&lt;p&gt;Of course, I shamelessly recommend &lt;a href="https://gettinggit.com"&gt;Getting Git&lt;/a&gt;. My video course covering the basic and advanced usage of all Git commands from the command line.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What if I have more questions?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Awesome. Send them &lt;a href="https://twitter.com/gonedark"&gt;to me on Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;small&gt;* &lt;em&gt;Photo by &lt;a href="https://unsplash.com/@jansn?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Bob Jansen&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Building Products - Building an audience</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Thu, 17 Jan 2019 16:19:27 +0000</pubDate>
      <link>https://dev.to/gonedark/building-products---building-an-audience-519f</link>
      <guid>https://dev.to/gonedark/building-products---building-an-audience-519f</guid>
      <description>&lt;p&gt;I recently published the second video in the series &lt;a href="https://www.youtube.com/watch?v=WZ-Q3pEEvUc&amp;amp;list=PLmwAMIdrAmK5QAtpDCkUzNdrU6IsAGRoR"&gt;Building Optionality&lt;/a&gt; where I share all the steps I take when building a new product from the ground up. As we discussed in the first video &lt;em&gt;Optionality&lt;/em&gt; is literally from the ground up as I'm also building an audience.&lt;/p&gt;

&lt;p&gt;This is a not an easy task, but a critical step. Too often developers overlook this step. However, it's important to emphasize that before you even start architecting or writing code for your product you need to do some initial marketing.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/gonedark/building-products---starting-from-square-0-3217"&gt;first article&lt;/a&gt;, I talked about how I planned to build a blog and start writing weekly content to cross post on Medium and community forums in an effort to build an audience.&lt;/p&gt;

&lt;p&gt;Now admittedly I didn't do much over the holidays, but I want to stay disciplined about making these posts and videos each step of the way.&lt;/p&gt;

&lt;p&gt;Since last time I probably spent roughly 10 hours on the project. Here's the breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 hours setting up the blog.&lt;/li&gt;
&lt;li&gt;6 hours drafting the first two posts.&lt;/li&gt;
&lt;li&gt;1 hour deploying everything to the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before I go through each of these steps in more detail, it's important to again point out that this isn't much time. Everything is MVP right now. And right now MVP means &lt;em&gt;minimal effort&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Furthermore, I still haven't built any of the product. Although I wish I had because I mismanaged a few trades during December’s downturn. No, right now all my effort is going into building the audience. I'm not down in my office cave hacking away at this huge application for weeks followed by some big bang launch.&lt;/p&gt;

&lt;p&gt;I'm going to continue to reiterate this because it’s one of the most important things about building products. In fact it parallels nicely with investing in general. Time is money. I don't want to spend a bunch of time building &lt;em&gt;Optionality&lt;/em&gt; when it may not generate a return on investment because there is no market.&lt;/p&gt;

&lt;p&gt;With that said, let's review each of the three things I did since last time.&lt;/p&gt;

&lt;p&gt;First, &lt;a href="https://dev.to/gonedark/jekyll-to-jigsaw-4017"&gt;I finished setting up Jigsaw&lt;/a&gt;. Jigsaw actually had a starter template which I was able to use. In fact, I don't know why I didn't see this the first time. Then I went back and watched the first video to verify they indeed updated the docs.&lt;/p&gt;

&lt;p&gt;I spent a little time tweaking it, which really meant I jumped out to Google Fonts to give me some a super simple, text-based masthead. Otherwise it's using the starter template. Again &lt;em&gt;minimal effort&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I did spend roughly 30 minutes adding a &lt;em&gt;Read Time&lt;/em&gt; feature. I justified this as I felt it helped improve the reading experience. Investment articles tend to be long, so I want to encourage potential readers they can get through these posts quickly. This also acts as a measure for me to keep them similar in length.&lt;/p&gt;

&lt;p&gt;A majority of time was spent drafting articles. I found it best to write two articles at a time as this allows me to get a week ahead. Everyone underestimates how much time goes into writing an article. You have to narrow a topic, write a draft, proofread, fact check, add images, tweak for SEO, cross post. It’s a process.&lt;/p&gt;

&lt;p&gt;Admittedly these first two were probably a bit slower as I was finding the right tone and structure. Although my programmer brain wants to dismiss these nuances, they are critical. These kinds of details help build an audience and ultimately build trust that &lt;em&gt;Optionality&lt;/em&gt; will be a useful product.&lt;/p&gt;

&lt;p&gt;Finally, I spent about an hour deploying the site. For right now I'm piggybacking some space on one of my existing web servers. While I’m optimistic for the future, &lt;a href="https://optionality.app"&gt;optionality.app&lt;/a&gt; currently gets little traffic. Again, &lt;em&gt;minimal effort&lt;/em&gt;. No need to purchase hosting, spin up servers, etc. If I didn’t have server space just sitting, I likely would have looked at Netlify or Amazon S3 before setting up my own server.&lt;/p&gt;

&lt;p&gt;On a similar technical note, sometimes as developers we also get caught up in the tools and services. This can be a pretty nasty time drain. Never underestimate the power of a command like &lt;code&gt;rsync&lt;/code&gt;. It's been around since the early days of UNIX and it still crushes the use case of synchronizing remote files.&lt;/p&gt;

&lt;p&gt;That's pretty much it this time. Soon I plan to start working on a fuller landing page with a newsletter sign-up. But as outlined in the first video, I need to get a bit closer to my goals before moving on to the next step.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Want more?&lt;/strong&gt; Subscribe to the video series on &lt;a href="https://www.youtube.com/watch?v=WZ-Q3pEEvUc&amp;amp;t=28s&amp;amp;list=PLmwAMIdrAmK5QAtpDCkUzNdrU6IsAGRoR&amp;amp;index=3"&gt;YouTube&lt;/a&gt; and send me your question or feedback on &lt;a href="https://twitter.com/gonedark"&gt;Twitter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Audience" cover photo by &lt;a href="https://www.flickr.com/photos/zemlinki/2845711637"&gt;Zemlinki!&lt;/a&gt; made available under &lt;a href="https://creativecommons.org/licenses/by/2.0/"&gt;CC BY 2.0&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productdevelopment</category>
    </item>
    <item>
      <title>Jekyll to Jigsaw</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Tue, 08 Jan 2019 13:57:19 +0000</pubDate>
      <link>https://dev.to/gonedark/jekyll-to-jigsaw-4017</link>
      <guid>https://dev.to/gonedark/jekyll-to-jigsaw-4017</guid>
      <description>&lt;p&gt;All these &lt;em&gt;year in review&lt;/em&gt; and &lt;em&gt;New Year's resolutions&lt;/em&gt; got me motivated. I decided use it to complete one of &lt;a href="https://dev.to/gonedark/2018-lookbehind-lookahead-2019-4pnn"&gt;my own goals for the year&lt;/a&gt; - redesign blog. This was more or less an impromptu hackathon, which I time boxed to 4 hours to ensure I didn’t go down the rabbit hole of intricately redesigning everything.&lt;/p&gt;

&lt;p&gt;This would be a simple facelift to modernize the template with a focus on copy, as well as a conversion of the static site generator. I decided to refactor my blog to &lt;a href="https://jigsaw.tighten.co/"&gt;Jigsaw&lt;/a&gt;. So this serves as not only my first article to christen the conversion, but also a review of the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why JigSaw
&lt;/h2&gt;

&lt;p&gt;My blog has been around for over a decade. I can't tell you how many times it's been converted. It originally started as static HTML, then &lt;em&gt;WordPress&lt;/em&gt;, then &lt;em&gt;Jekyll&lt;/em&gt;, then &lt;em&gt;GitHub Pages&lt;/em&gt;, then &lt;em&gt;Ghost&lt;/em&gt;, then back to &lt;em&gt;Jekyll&lt;/em&gt;. And now, of course, Jigsaw.&lt;/p&gt;

&lt;p&gt;Historically I used this as an opportunity to try new tech stacks. Nowadays, this is rather impractical for a few reasons.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A blog doesn't really push technical boundaries. So while it may serve as an introduction, it's not going to substantiate its use for other things.&lt;/li&gt;
&lt;li&gt;My time is better spent elsewhere. If it's not a good learning opportunity, just go with something familiar. Jigsaw has a PHP core and leverages Laravel Blade templates engine. It also included a &lt;a href="https://jigsaw.tighten.co/docs/starter-templates/"&gt;starter template&lt;/a&gt; developed with &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt; and a little &lt;a href="https://vuejs.org/"&gt;Vue.js&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Both of these combined bring me to my final reason of convenience. Writing blog post is hard enough already, I don't want anything to make it harder. While Jigsaw allows me to use Blade, I can continue to use Markdown.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the end, for me, Jigsaw balanced my time by being convenient to work with (PHP + Blade + Markdown) while still giving me some light learning opportunities (TailwindCSS + Vue.js).&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting front matter
&lt;/h2&gt;

&lt;p&gt;Although front matter is pretty straightforward, I created a lot custom keys over the years while transitioning between all the static generators. So I wrote a quick script to condense these down (and reformat) to the minimal amount of: &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;categories&lt;/code&gt;, and a few SEO keys.&lt;/p&gt;

&lt;p&gt;Here's a &lt;a href="https://gist.github.com/jasonmccreary/af977128c87cb8404515f103e3141d7f"&gt;Gist of the conversion script&lt;/a&gt; I wrote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rewriting URLs
&lt;/h2&gt;

&lt;p&gt;Another motivation for this redesign was to finally switch to &lt;a href="https://jasonmccreary.me"&gt;jasonmccreary.me&lt;/a&gt;. I purchased this domain a while back, but had not made it primary. Since I was going to change the link structure for each of my posts anyway, I took the opportunity to do both.&lt;/p&gt;

&lt;p&gt;The key thing was ensuring my URLs redirected so I didn't lose my search engine rankings. I made sure to switch the proper settings in Google Search Console and Google Analytics, as well as generating &lt;code&gt;301&lt;/code&gt; redirects for each post. There was also some tweaks to the Jigsaw config and template to ensure generated URLs consistently included the trailing slash.&lt;/p&gt;

&lt;p&gt;Here's a &lt;a href="https://gist.github.com/jasonmccreary/2eef6508bba04703ce202612f76ececd"&gt;gist of these scripts&lt;/a&gt; to convert the Jekyll posts dated filenames to the dasherized Jigsaw post filenames and generate the &lt;code&gt;301&lt;/code&gt; redirects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tweaking categories
&lt;/h2&gt;

&lt;p&gt;For the most part Jigsaw was a straight conversion. The only thing that took a minute was configuring the categories. The documentation was a bit light on how these are set up (possible open source contribution…). Again since I was familiar with PHP and Blade, it wasn't too hard to dig around the code and figure it out.&lt;/p&gt;

&lt;p&gt;Initially, it wasn't automatically generating the category pages (or collections). Ultimately, there is an &lt;code&gt;source/_categories&lt;/code&gt; folder within the start template where I needed to create markdown files for each of my categories.&lt;/p&gt;

&lt;p&gt;That wasn't quite it though. The &lt;code&gt;categories&lt;/code&gt; closure in &lt;code&gt;config.php&lt;/code&gt; also needed some tweaks. Especially since my category names were titles and contained spaces. I had two options, I could add code to generate the lowercase, dasherized URLs in the template or I could do so at build time.&lt;/p&gt;

&lt;p&gt;Inline with my goal to keep the writing experience easy, I preferred to generate these properly at build time. So I changed the config to lowercase and dasherize the categories names from the front matter and properly group the posts. Here's the specific code as well as a &lt;a href="https://gist.github.com/jasonmccreary/9890185a5cf9644b5bb1fa5fd772d263"&gt;Gist of the complete &lt;code&gt;config.php&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'posts'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$allPosts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$allPosts&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getFilename&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;in_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding Read Time
&lt;/h2&gt;

&lt;p&gt;Jigsaw also has fancy &lt;a href="https://jigsaw.tighten.co/docs/helper-methods/"&gt;helper methods&lt;/a&gt;. This is pretty nice as it was a pain to customize such things and Jekyll - often requiring overriding or monkey patching in Ruby. With Jigsaw I simply add a closure in &lt;code&gt;config.php&lt;/code&gt; and can reference it through the &lt;code&gt;$page&lt;/code&gt; object just like I do the front matter.&lt;/p&gt;

&lt;p&gt;This made it super easy to create something I wanted to add to my articles for a while - &lt;em&gt;Read Time&lt;/em&gt;. It's a nice little UX hack to see an estimate of the time it will take you to read an article. I derived the formula from some of &lt;a href="https://marketingland.com/estimated-reading-times-increase-engagement-79830"&gt;these calculations&lt;/a&gt;. Here's the specific code and also in the &lt;a href="https://gist.github.com/jasonmccreary/9890185a5cf9644b5bb1fa5fd772d263"&gt;Gist of the complete &lt;code&gt;config.php&lt;/code&gt;&lt;/a&gt;. I simply call &lt;code&gt;$post-&amp;gt;readTime()&lt;/code&gt; within my templates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'readTime'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;intval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str_word_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;strip_tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All in all it took about 4 hours for the conversion. 2 hours were massaging the front matter, and another hour was battling the category configuration. So, in fairness, it really only took about an hour to set up Jigsaw using the starter template and begin customizing.&lt;/p&gt;

&lt;p&gt;I plan to revisit the design, especially after reading &lt;a href="https://refactoringui.com/"&gt;Refactoring UI&lt;/a&gt; and incorporate pages for my various &lt;a href="https://basecodefieldguide.com"&gt;products&lt;/a&gt; and &lt;a href="https://jasonmccreary.me/articles/mentoring-pair-programming-development-coaching/"&gt;services&lt;/a&gt;. I like doing a little bit each time I write an article. I'll write a post and spend 15 minutes making other tweaks. So well I wouldn't call it done, I will check the box for my first 2019 goal of 2019 two redesign my blog.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Have more questions about Jigsaw?&lt;/strong&gt; Ask me here or on &lt;a href="https://twitter.com/gonedark"&gt;Twitter&lt;/a&gt;. I'm glad to answer and considering packaging up some of my customizations or contributing them to the starter template.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>blogging</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>2018 Lookbehind, Lookahead 2019</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Wed, 02 Jan 2019 13:29:55 +0000</pubDate>
      <link>https://dev.to/gonedark/2018-lookbehind-lookahead-2019-4pnn</link>
      <guid>https://dev.to/gonedark/2018-lookbehind-lookahead-2019-4pnn</guid>
      <description>&lt;p&gt;Every year I make goals. Most of my goals are focused on work, but I do squeeze a few personal goals in as well. Last year I publicized my &lt;a href="https://dev.to/gonedark/2018-dev-goals-4abd"&gt;2018 Dev Goals&lt;/a&gt;. So, before talking about my 2019 goals, let's lookbehind at 2018.&lt;/p&gt;

&lt;h2&gt;
  
  
  2018 Goals
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Write a book
&lt;/h3&gt;

&lt;p&gt;I published the early release of &lt;a href="https://basecodefieldguide.com"&gt;BaseCode&lt;/a&gt; on July 13, and the full edition on September 12. That's not entirely true, the final &lt;em&gt;Exit&lt;/em&gt; chapter was published December 3.&lt;/p&gt;

&lt;p&gt;I had code samples, resources, and the practices in my head well before writing &lt;em&gt;BaseCode&lt;/em&gt;. Even with all this ready, it still took longer than I expected. For me writing wasn't the hard part, it was putting it together: proofreading, formatting.&lt;/p&gt;

&lt;p&gt;Another delay we're all the add-ons. It would've been better to have more complete for the initial release. When I released &lt;em&gt;BaseCode&lt;/em&gt; I sold different &lt;em&gt;kits&lt;/em&gt;. This put a lot of pressure on me to finish quickly. Not necessarily from others, but myself.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;BaseCode&lt;/em&gt; didn't do as well financially as I expected. I still believe &lt;em&gt;BaseCode&lt;/em&gt; fills a gap for intermediate developers. So there is an audience. But marketing is another beast. I did better this time with a newsletter and tweets. Where I missed the mark was the release. Particularly around having influencers help me reach a larger audience in a focused, timely effort. Part of this was intentional though. I know others were willing to help, but I wanted to see how much I could do on my own. Ultimately sales for these types of products just have that initial pop, but there can also be a long tail. I expect &lt;em&gt;BaseCode&lt;/em&gt; will bring in sales over the next few years and might eventually reach it's financial goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Learn Python
&lt;/h3&gt;

&lt;p&gt;I didn't complete this one. The reason I chose Python was for data processing. My intentions were to use it for an investments analytics tool I never got around to building. Otherwise I had no need for using Python day-to-day and hence why I didn't reach this goal.&lt;/p&gt;

&lt;p&gt;Python is something I may still learn someday, but it's going to have to come out of necessity. There's really no reason for me to force spending time learning it in the face of my other goals.&lt;/p&gt;

&lt;h3&gt;
  
  
  ➖ Expand Shift services
&lt;/h3&gt;

&lt;p&gt;I did add more shifts in 2018, I have to be honest that I didn't technically expand the services in the way I wanted. This is still in progress, but it won't make the cut for 2018 and will carryover as a partial goal to 2019.&lt;/p&gt;

&lt;p&gt;In particular, I wanted to add a subscription to allow users to run shifts as part of their continuous integration tools. This requires subscription billing, additional Shift, web hooks, API keys, capacity. So it is something that will would have been difficult to complete entirely in 2018 regardless. It may even be something that carries on longer than 2019.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Speak at five conferences
&lt;/h3&gt;

&lt;p&gt;In 2018 I spoke at 13 conferences. 13! I crushed this goal. There won't be another year like this. While I enjoyed every conference, it was too much. In 2019, I will be more selective about which conferences I submit too, what topics I submit, and ultimately accept - ideally only speaking at conferences which directly relate to my products and services or a desirable location.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Reach 10k Twitter followers
&lt;/h3&gt;

&lt;p&gt;Just like learning Python, I failed this one pretty epically as well. In 2018 I didn't even increase my Twitter followers more than 2017. Currently I'm barely halfway to 10k with 4,800 followers.&lt;/p&gt;

&lt;p&gt;Reaching this goal requires a constant presence and well-crafted content. Although I always try to do the latter, the former is where I failed. This is something I will continue to focus on, but likely without the pressure of being a goal. I'll leave it as something that will hopefully happen organically.&lt;/p&gt;

&lt;h2&gt;
  
  
  2019 Goals
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Redesign Blog
&lt;/h3&gt;

&lt;p&gt;It's been several years since I've redesigned my blog. It's looking pretty outdated. This has led me to posting content on other sites like Dev.to and Medium instead of first posting here. I also plan to switch the domain to &lt;a href="http://jasonmccreary.me"&gt;jasonmccreary.me&lt;/a&gt; which I picked up during a Black Friday sale.&lt;/p&gt;

&lt;p&gt;Admittedly, this is a pretty easy goal. But it's good to start with some quick wins to get the momentum going for the year. I've found when I try to start the year with a large goal, I spend all my effort on it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Less talks, more workshops
&lt;/h3&gt;

&lt;p&gt;As I mentioned before, I plan to speak at conferences less. But speaking is something I still enjoy and want to continue. I think I'm good at spotting gaps in knowledge. It's usually not the latest fancy code or trends, but often more fundamental topics which need attention. These get overlooked, but in reality are the things we use every day and will carry us farther.&lt;/p&gt;

&lt;p&gt;In 2017 I ran a few online workshops. Most were free, some were paid. I plan to hold a few in 2019.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contribute to open source projects
&lt;/h3&gt;

&lt;p&gt;Although I primarily contribute to the community through education, I want to contribute through code as well in 2019. The obvious candidate is to contribute more to Laravel. I have a few areas of the framework I'd like to give some attention. So I plan to learn more about the current code and see where I might be able to make a few contributes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Improve frontend technologies
&lt;/h3&gt;

&lt;p&gt;I've been a firm believer in separation of frontend and backend - particularly through APIs. I think this is and established trend and one that will continue. In 2019, I plan to go "API first" on any new project and potentially refactor some existing projects as well. This doesn't not necessarily mean single page app, but I have an opportunity to learn more technologies such as Vue, React, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Optionality
&lt;/h3&gt;

&lt;p&gt;The underlying intention of learning Python was to build an investment analytics tool. That tool has pivoted into &lt;em&gt;Optionality&lt;/em&gt;. Building &lt;a href="https://optionality.app"&gt;Optionality&lt;/a&gt; has been an intentionally slow, nuanced MVP process. However, this is a tool I plan to use personally. While I plan to honor the MVP approach and share my progress, it is something I will nonetheless build. If nothing else, to scratch my own itch. Just like a quick win, I believe you need a pet project as well.&lt;/p&gt;

</description>
      <category>yearinreview</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>Building Products - Starting from Square 0</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Tue, 18 Dec 2018 15:15:34 +0000</pubDate>
      <link>https://dev.to/gonedark/building-products---starting-from-square-0-3217</link>
      <guid>https://dev.to/gonedark/building-products---starting-from-square-0-3217</guid>
      <description>

&lt;p&gt;Lately I've been preparing build a new SaaS product called &lt;a href="https://optionality.app"&gt;Optionality&lt;/a&gt;. I want to journal this process to not just talk about the code, but also the product decisions and marketing involved in building a product.&lt;/p&gt;

&lt;p&gt;So in this first post, I want to start at the very beginning. It's important because I rarely start with writing code. As developers, when we think of an idea we get lost in the technical details. We start pre-architecting, scaling out servers, and picking the latest tech stack to build it all.&lt;/p&gt;

&lt;p&gt;While this is, of course, fun to think about, you can’t jump right into writing code. Too often people, not just developers, but people in general, teams, companies jump straight into building. This is a mistake.&lt;/p&gt;

&lt;p&gt;The reality is all you have is an &lt;em&gt;idea&lt;/em&gt;. It's really nothing. At best a few ions isolated in your brain. You have to bring the idea into the world bit by bit, proving and shaping along the way.&lt;/p&gt;

&lt;p&gt;For example, with &lt;a href="https://gettinggit.com"&gt;Getting Git&lt;/a&gt;, I led conference training before I recorded the video course. If I hadn’t given this at multiple conferences to full audiences, I wouldn’t have made the course. In fact, I originally planned to record a second course, but am waiting based on the response from the first before continuing with the idea.&lt;/p&gt;

&lt;p&gt;With my book, &lt;a href="https://basecodefieldguide.com"&gt;BaseCode&lt;/a&gt;, I spoke at conferences, but also did a &lt;a href="https://twitter.com/i/moments/948577473742233600"&gt;series of tweets&lt;/a&gt; to narrow down the topics. These tweets were a way to prove the idea and, relatively speaking, got a large number of likes and retweets.&lt;/p&gt;

&lt;p&gt;Form there I created a mailing list. I think it was &lt;a href="http://www.fullstackradio.com/42"&gt;Justin Jackson&lt;/a&gt; that said if you don’t get 500 subscribers you probably don't have a good idea. Others like &lt;a href="https://nathanbarry.com/"&gt;Nathan Barry&lt;/a&gt; and &lt;a href="https://twitter.com/adamwathan"&gt;Adam Wathan&lt;/a&gt; constantly talk about the importance of a landing page to build your audience. This was key for &lt;em&gt;BaseCode&lt;/em&gt; and definitely led to a more successful product than &lt;em&gt;Getting Git&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now this new SaaS will be even more challenging because it’s a different industry. For almost as long as I’ve been programming, I’ve been investing in the stock market. In the past few years, I’ve advanced into options trading. What I’ve noticed is a lack of tools around portfolio tracking and analysis.&lt;/p&gt;

&lt;p&gt;Brokers offer this at a very basic level, but their tools focus more on trading. As a member of a few investment communities it seems most people use some kind of spreadsheet - which is a terrible, manual experience.&lt;/p&gt;

&lt;p&gt;So I identified this gap. But again, this isn’t proof &lt;em&gt;if I build it they will come&lt;/em&gt;. I’ve really only proven a need. To that point, the best ideas start by filling a personal need. If it’s not something I would use, it’s unlikely others will use it. You have to be willing to &lt;em&gt;eat your own dog food&lt;/em&gt;. If not, your heart won’t be into building it and you're more likely to give up.&lt;/p&gt;

&lt;p&gt;Now, before I run to my office cave to build this, I want to prove the market more. In order to do that, I need to grow my audience. I created a separate &lt;a href="https://twitter.com/TraderJMac"&gt;Twitter handle&lt;/a&gt;. Because of the cross over, I immediately got about 100 followers. These were developers who also share my passion for investing. However, I need to grow my true investor audience.&lt;/p&gt;

&lt;p&gt;I started by writing weekly threaded tweets. Unfortunately it’s not growing my followers because, well, this is a new account and no one knows who the hell I am. My new plan is to take these threaded tweets and add some graphs and images to turn them into articles I can publish on &lt;a href="https://optionality.app"&gt;Optionality&lt;/a&gt;. I will then cross-post on Medium, within investing communities, etc.&lt;/p&gt;

&lt;p&gt;Remember, I don't have an audience. So I'm not even at a place where I can start to validate my idea with potential users. I'm not even at &lt;em&gt;Square 1&lt;/em&gt;, I'm at &lt;em&gt;Square 0&lt;/em&gt;. I have to try and grow the audience first. This needs to happen before deep-diving into writing code or architecting this portfolio tracker platform. That doesn’t mean we won’t write any code. But it’s not the app code as you might think. In fact the first thing I need to code is a blog to hold these articles.&lt;/p&gt;

&lt;p&gt;I’m going to do this with &lt;a href="https://jigsaw.tighten.co/"&gt;Jigsaw&lt;/a&gt;. It’s a static site generator. Nothing fancy, just converts markdown to HTML and places it within a site template. No reason to install some heavy software or hand-code my own blog. I always want to do the simplest thing. Everything is an MVP.&lt;/p&gt;

&lt;p&gt;Arguably the simplest thing would be to post on &lt;em&gt;Medium&lt;/em&gt; under one of the investment tags. But, I need to start building a search engine presence. Optimistically, when I do build this product, I want people to be directed to &lt;a href="https://optionality.app"&gt;Optionality&lt;/a&gt;, not &lt;em&gt;Medium&lt;/em&gt;. So while using &lt;em&gt;Medium&lt;/em&gt; directly and linking back to &lt;em&gt;Twitter&lt;/em&gt; would be simpler, there’s value in centralizing the content with little extra cost.&lt;/p&gt;

&lt;p&gt;Another point is I could have used &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; or &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt;. Underneath, Jekyll is Ruby and Jigsaw is PHP (with hints of Laravel). While I am familiar with Jekyll, I am more with PHP and Laravel in general.&lt;/p&gt;

&lt;p&gt;This is an important point because far too often developers try to pair a new idea with a new technology. This adds unnecessary complexity, ultimately lowering your probability of success. Not only are you learning your idea, you’re also learning the technology.&lt;/p&gt;

&lt;p&gt;In the end, I balance the MVP approach while being mindful each iteration keeps me on the path towards my ultimate goal. It's not necessarily for each iteration to get you there faster or completely, but it should keep you on the path.&lt;/p&gt;

&lt;p&gt;Now before I launch this step, I want to be clear with two more things. First, my timeline. Timelines are very important. They force accountability and reinforce the MVP approach. You can't have forever to reach your goal. Second, I need to outline measurable objectives of my goal. What am I trying to do and how can I verify it's working.&lt;/p&gt;

&lt;p&gt;For &lt;em&gt;Square 0&lt;/em&gt;, my goal is to grow my audience. I'm going to give myself 4 weeks to do so. I plan to achieve this goal by the following measurable objectives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Weekly blog posts cross-posted to Medium, Twitter, and investment communities.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sub-goal:&lt;/strong&gt; Have post syndicated on Medium.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Increase traffic to &lt;em&gt;optionality.app&lt;/em&gt; measured by Google Analytics referrer and content report.&lt;/li&gt;
&lt;li&gt;Increase Twitter following to 250 people.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will say, some of these are a stretch. But I have to start somewhere and hold myself accountable to measurement. So we'll see in 4 weeks if these goals are met and I should continue on with building my product.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Want to follow along?&lt;/strong&gt; Be sure to subscribe to &lt;a href="https://dev.to/gonedark"&gt;follow me on Dev.to&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=J-0HpAUb8g0&amp;amp;list=PLmwAMIdrAmK5QAtpDCkUzNdrU6IsAGRoR"&gt;subscribe on YouTube&lt;/a&gt; for more posts and videos.&lt;/em&gt;&lt;/p&gt;


</description>
      <category>productdevelopment</category>
    </item>
    <item>
      <title>Black Friday Deals</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Fri, 23 Nov 2018 14:15:18 +0000</pubDate>
      <link>https://dev.to/gonedark/black-friday-deals-10ic</link>
      <guid>https://dev.to/gonedark/black-friday-deals-10ic</guid>
      <description>&lt;p&gt;Just a place to share and discuss the "Black Friday" specials to help us devs save a buck on good products, services, and resources. 🤑&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>10 practices for writing readable code</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Tue, 18 Sep 2018 16:04:14 +0000</pubDate>
      <link>https://dev.to/gonedark/10-practices-for-readable-code-143a</link>
      <guid>https://dev.to/gonedark/10-practices-for-readable-code-143a</guid>
      <description>&lt;p&gt;I've been writing code for 20 years. During that time I've worked with 17 teams coding different languages to build hundreds of projects. These include everything from a simple blog site, to &lt;a href="https://jason.pureconcepts.net/2013/03/why-i-leave-a-job/"&gt;APIs&lt;/a&gt; supporting 3,000 requests/second, to &lt;a href="https://jason.pureconcepts.net/2014/03/successful-app-fail/"&gt;top selling apps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From these experiences, combined with &lt;a href="https://jason.pureconcepts.net/2014/09/the-reading-list/"&gt;the books I've read&lt;/a&gt;, it's become apparent to me what matters most in code: &lt;strong&gt;readability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On the surface, readability may seem subjective. Something which may vary between languages, codebases, and teams. But when you look underneath, there are core elements within all code which make it readable.&lt;/p&gt;

&lt;p&gt;Many programmers are too close to the computer. If the code runs, nothing else matters. Although a common defense it removes all of the human elements from what we do.&lt;/p&gt;

&lt;p&gt;Over the last several months I've worked to distill these elements into 10 practices for writing code with a focus on improving readability and decreasing complexity. I've written about these in detail and applied them to real-world code snippets in &lt;a href="https://basecodefieldguide.com"&gt;BaseCode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Many will unfortunately dismiss these as too trivial. Too fundamental. But I assure you, every bit of bad code I've encountered has failed to apply these practices. And every bit of good code you find one, if not many, of these practices.&lt;/p&gt;




&lt;h2&gt;
  
  
  Formatting
&lt;/h2&gt;

&lt;p&gt;So much energy is wasted on formatting. Tabs versus spaces. Allman versus K&amp;amp;R. You'll reach a point where you realize formatting is &lt;strong&gt;not what matters&lt;/strong&gt; in programming. Adopt a standard format, apply it to the codebase, and automate it. Then you can refocus that energy on actually writing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dead code
&lt;/h2&gt;

&lt;p&gt;All those commented blocks, unused variables, and unreachable code are rot. They effectively say to the reader, &lt;em&gt;"I don't care about this code"&lt;/em&gt;. So a cycle of decay begins. Over time this dead code will kill your codebase. It's classic &lt;a href="https://en.wikipedia.org/wiki/Broken_windows_theory"&gt;Broken Windows Theory&lt;/a&gt;. You must seek and destroy dead code. While it doesn't need to be your primary focus, always be a &lt;a href="https://jason.pureconcepts.net/2015/01/are-you-a-boy-scout/"&gt;Boy Scout&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nested code
&lt;/h2&gt;

&lt;p&gt;The foundation of nearly all code is logic. We write code to make decisions, iterations, and calculations. This often results in branches or loops which create deeply nested blocks of code. While this may be easy to track for a computer, it can be a lot of mental overhead for a human. As such, the code appears complex and unreadable. Unravel nested code by using guard clauses, early returns, or aspects of functional programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using objects
&lt;/h2&gt;

&lt;p&gt;Despite the current era of Object Oriented Programming, we still have &lt;a href="https://blog.codinghorror.com/code-smells/"&gt;Primitive Obsession&lt;/a&gt;. We find this in long parameter lists, data clumps, and custom array/dictionary structures. These can be refactored into objects. Doing so not only formalizes the structure of the data, but provides a home of all that repeat logic which accompanies the primitive data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big Blocks
&lt;/h2&gt;

&lt;p&gt;While I don't adhere to hard numbers, code blocks can reach a critical length. When you determine you have a &lt;em&gt;big block&lt;/em&gt; of code, there's an opportunity to &lt;em&gt;recognize&lt;/em&gt;, &lt;em&gt;regroup&lt;/em&gt;, and &lt;em&gt;refactor&lt;/em&gt; the code. This simple process allows you to determine the context and abstraction level of the code block so you can properly identify the responsibilities and refactor the code into a more readable and less complex block.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming
&lt;/h2&gt;

&lt;p&gt;Sure, &lt;em&gt;naming things is hard&lt;/em&gt;. But only because we make it hard. There's a little trick which works well with many things in programming, including naming - &lt;em&gt;deferral&lt;/em&gt;. Don't ever get stuck naming something. Just keep coding. Name a variable a sentence if you must. Just keep coding. I guarantee by the time you complete the feature or work a better name will have presented itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing Comments
&lt;/h2&gt;

&lt;p&gt;This single practice was the original game changer for me. It's what put me on the path of focusing on readability. Despite &lt;a href="https://jason.pureconcepts.net/2015/03/removing-comments/"&gt;my efforts to explain&lt;/a&gt;, there's always at least one person who hates me for it. They have that one example where a comment was absolutely necessary. Sure, when the Hubble telescope telemetry system has to interface with a legacy adapter by return &lt;code&gt;687&lt;/code&gt; for unknown readings then that may need to be communicated with a comment. But for pretty much everything else, you should challenge yourself to rewrite the code so it doesn't need a comment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reasonable Returns
&lt;/h2&gt;

&lt;p&gt;We return the oddest values for things. Especially for boundaries cases. Values like &lt;code&gt;-1&lt;/code&gt;, or &lt;code&gt;687&lt;/code&gt;, or &lt;code&gt;null&lt;/code&gt;. In turn, a lot of code is written to handle these values. In fact, the creator of &lt;code&gt;null&lt;/code&gt; calls it &lt;a href="https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare"&gt;The Billion Dollar Mistake&lt;/a&gt;. You should aim to return a more reasonable value. Ideally something that allows the calling code to carry on even in the event of a &lt;em&gt;negative path&lt;/em&gt;. If there are truly exceptional cases, there are better ways to communicate them than &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule of Three
&lt;/h2&gt;

&lt;p&gt;Think of a mathematical series of numbers. I provide you with the number &lt;code&gt;2&lt;/code&gt; and ask, &lt;em&gt;"What's next?"&lt;/em&gt; Maybe it's &lt;code&gt;3&lt;/code&gt; or &lt;code&gt;4&lt;/code&gt;, but maybe it's &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;2.1&lt;/code&gt;. In reality you have no idea. So, I provide another number in the series &lt;code&gt;2, 4&lt;/code&gt; and ask, &lt;em&gt;"What's next?"&lt;/em&gt; Maybe it's &lt;code&gt;6&lt;/code&gt; or &lt;code&gt;8&lt;/code&gt; or &lt;code&gt;16&lt;/code&gt;. Again, despite our increased confidence we don't really know. Now I provide another number in the series &lt;code&gt;2, 4, 16&lt;/code&gt; and ask, &lt;em&gt;"What's next?"&lt;/em&gt; Now with three data points our programmer brains see the squared series and determine the next number to be &lt;code&gt;256&lt;/code&gt;. That's the &lt;em&gt;Rule of Three&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The example demonstrates without distracting us with code that we shouldn't predetermine an abstraction or design right away. The Rule of Three counteracts our need to fight duplication by deferring until we have more data to make an informed decision. In the &lt;a href="https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction"&gt;words of Sandi Metz&lt;/a&gt;, _"duplication is far cheaper than the wrong abstraction."&lt;/p&gt;

&lt;h2&gt;
  
  
  Symmetry
&lt;/h2&gt;

&lt;p&gt;Now for the final practice and one which gives any bit of code that lasting touch of near poetic readability - symmetry. This is pulled straight from Kent Beck's &lt;a href="https://www.amazon.com/Implementation-Patterns-Kent-Beck/dp/0321413091"&gt;Implementation Patterns&lt;/a&gt; which simply states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Symmetry in code is where the same idea is expressed the same way everywhere it appears.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is easier said than done. Symmetry embodies the creative side of writing. It's underlies many of the other practice: naming, structure, objects, patterns. It may vary language to language, codebase to codebase, and team to team. As such, you could spend the term of your natural life pursuing it. Yet, once you start applying symmetry to your code, &lt;a href="https://twitter.com/gonedark/status/1041716025862119425"&gt;a purer form appears&lt;/a&gt; and the code takes shape quickly.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;These were a high-level view of the practices within _BaseCode&lt;/em&gt;. I encourage you check out the resources linked in this post, &lt;a href="https://www.youtube.com/watch?v=s9LwS6RFax0&amp;amp;index=2&amp;amp;t=14s&amp;amp;list=PLmwAMIdrAmK7cjLLYrKppUhaR2ywTuKhm"&gt;watch screencasts&lt;/a&gt; applying these practices, or read about them in full detail applied to real-world code snippets in &lt;a href="https://basecodefieldguide.com"&gt;BaseCode&lt;/a&gt;._&lt;/p&gt;

</description>
      <category>programming</category>
      <category>practices</category>
      <category>learning</category>
    </item>
    <item>
      <title>Untangling Nested Code</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Mon, 16 Jul 2018 14:55:31 +0000</pubDate>
      <link>https://dev.to/gonedark/untangling-nested-code-1h0a</link>
      <guid>https://dev.to/gonedark/untangling-nested-code-1h0a</guid>
      <description>&lt;p&gt;I don’t believe in hard rules for writing code. You hear them often. Things like methods shouldn’t be more than &lt;strong&gt;15&lt;/strong&gt; lines. Methods should only have &lt;strong&gt;one&lt;/strong&gt; &lt;code&gt;return&lt;/code&gt; statement. Indentation must be &lt;strong&gt;4 spaces&lt;/strong&gt;. Such rules are too rigid.&lt;/p&gt;

&lt;p&gt;In the real world code is much more fluid. Adhering to these hard rules distracts us from what really matters - &lt;em&gt;readability&lt;/em&gt;. If my focus is strictly on the number of lines or &lt;code&gt;return&lt;/code&gt; statements, I prevent myself from writing more readable code simply because it is a few lines "too long" or has more than one &lt;code&gt;return&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;Many of these hard rules attempt to address nested code. Nested code is hard to follow. Physically there’s more visual scanning with the eyes. Mentally, each level of nesting requires more overhead to track functionality. All of these exhaust a reader.&lt;/p&gt;

&lt;p&gt;Nested code is mostly the result of conditionals. Since conditionals are the basis for all programming logic, we can’t very well remove them. We must recognize their effect on readers and take steps to minimize this impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting back on top
&lt;/h2&gt;

&lt;p&gt;To improve readability, we want to bring the code back to the top level. By nature, loops and conditionals have a nested structure. There's no way to avoid nesting within these blocks. However, we can avoid nesting beyond this structure.&lt;/p&gt;

&lt;p&gt;Let's take a look at a few examples of nested code and practices for improving their readability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Empty blocks
&lt;/h3&gt;

&lt;p&gt;You may not believe me, but I've seen the following code more than once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Closure&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'APP_ENV'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'development'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// do nothing...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getScheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'https'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;forceScheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://www.example.com/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getPath&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;That's right, an empty &lt;code&gt;if&lt;/code&gt; block. I've also seen the opposite - an empty &lt;code&gt;else&lt;/code&gt; block. There is no rule that an &lt;code&gt;if&lt;/code&gt; must be paired with an &lt;code&gt;else&lt;/code&gt; - at least not in any of the programming languages I've used in the past 20 years. Empty blocks are &lt;em&gt;dead code&lt;/em&gt;, remove them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conditional values
&lt;/h3&gt;

&lt;p&gt;Nested code blocks often return a value. When these are boolean values, there's an opportunity to condense the code block and return the condition directly.&lt;/p&gt;

&lt;p&gt;Consider the nested code within the &lt;code&gt;isEmpty&lt;/code&gt; method of a &lt;code&gt;Set&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this method block is only 4 lines of code, it contains multiple sub-blocks. Even for such a small number of lines this is hard to read, making the code appear more complex than it really is.&lt;/p&gt;

&lt;p&gt;By identifying the conditional return of raw boolean values we have the rare opportunity to completely remove the nested code by directly returning the condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given the context of this aptly named method combined with a now one line block, we decreased its perceived complexity. Although this line may appear dense, it is nonetheless more readable than the original.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; Condensing conditionals can work for more data types than raw booleans. For example, you can  return the condition as an integer with a simple type cast. However this rapidly increases the complexity. Many programmers try to combat this by using a ternary. But a ternary condenses the code without decreasing the complexity, making the code less readable. In these cases, a guard clause is a better alternative.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Guard clauses
&lt;/h3&gt;

&lt;p&gt;Nested code is often the result of logical progression. As programmers we write out each condition until we reach a level where it's &lt;em&gt;safe&lt;/em&gt; to perform the action.&lt;/p&gt;

&lt;p&gt;While this flow may be ideal for execution, it's not ideal for reading. For each nested level the reader has to maintain a growing mental model.&lt;/p&gt;

&lt;p&gt;Consider the following implementation of the &lt;code&gt;add&lt;/code&gt; method of a &lt;code&gt;Set&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logically the progression: if the &lt;em&gt;item&lt;/em&gt; is not &lt;code&gt;null&lt;/code&gt; and if the &lt;code&gt;Set&lt;/code&gt; does not contain the &lt;em&gt;item&lt;/em&gt;, then add it.&lt;/p&gt;

&lt;p&gt;The problem is not only the perceived complexity of such a simple action, but that the primary action of this code is buried at the deepest level.&lt;/p&gt;

&lt;p&gt;Ideally the primary action of a block of code is at the top level. We can refactor the conditional to a guard clause to unravel the nested code and expose the primary action.&lt;/p&gt;

&lt;p&gt;A guard clause simply protects our method from exceptional paths. Although they commonly appear at the top of a code block, they can appear anywhere. We can convert any nested conditional into a guard clause by applying &lt;a href="https://en.wikipedia.org/wiki/De_Morgan%27s_laws"&gt;De Morgan's Laws&lt;/a&gt; and relinquishing control. In code, this means we negate the conditional and introduce a &lt;code&gt;return&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;By applying this to the &lt;code&gt;add&lt;/code&gt; method our implementation becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In doing so we have not only drawn out the primary action, but emphasized the exceptional paths for our method. It is now less complex for future readers to follow. It's also easier to test as the exceptional paths are clearly drawn out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Switching to if
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;switch&lt;/code&gt; statement is a very verbose code structure. &lt;code&gt;switch&lt;/code&gt; inherently has 4 keywords and 3 levels. It's a lot to read even if the contained blocks of code are only a few lines. While this is acceptable in certain cases, it's not in others.&lt;/p&gt;

&lt;p&gt;There are a few cases where using &lt;code&gt;if&lt;/code&gt; statements instead of a &lt;code&gt;switch&lt;/code&gt; statement may produce more readable code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When there are just a few &lt;code&gt;case&lt;/code&gt; blocks the inherent structure of the &lt;code&gt;switch&lt;/code&gt; statement produces more lines than the equivalent &lt;code&gt;if&lt;/code&gt; statements.&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;case&lt;/code&gt; blocks contain nested code the complexity increases and readability decreases to a critical level. Using guard clauses or adopting the practices within &lt;em&gt;Big Blocks&lt;/em&gt; can improve the code.&lt;/li&gt;
&lt;li&gt;When type casts or calculations are needed to coax the value into the constraints of a &lt;code&gt;switch&lt;/code&gt;. This doesn't apply to languages (Swift, Go, etc) that support more complex &lt;code&gt;case&lt;/code&gt; comparisons.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;switch&lt;/code&gt; statements are best when a 1:1 ratio exists between &lt;code&gt;case&lt;/code&gt; statements and the lines of code within their blocks. Whether these lines are assignments, &lt;code&gt;return&lt;/code&gt; statements, or method invocations the readability remains nearly the same provided the ratio is roughly 1:1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'action'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;startRecording&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'cut'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;stopRecording&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'lights'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;adjustLighting&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; In such cases where &lt;code&gt;switch&lt;/code&gt; statements are streamlined, many programmers use a map, database table, or polymorphism instead. All of which are indeed additional alternatives. Just remember every solution has trade-offs (complexity). A &lt;code&gt;switch&lt;/code&gt; statement is often "good enough" for most code.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Complex loops
&lt;/h3&gt;

&lt;p&gt;Another common form of nested code are loops. Loops by nature are complex. As programmers, we're cursed to be off by one and miss incremental logic. Again, we're humans not computers. So we're unlikely to win the battle against loops. They will always challenge us. The only way to combat this complexity is readability. &lt;/p&gt;

&lt;p&gt;I won't get into which data structures and algorithms may help improve your code. That is much too specialized. In general though, most loops deal with accumulation or invocation. If you find your codebase contains lots of loops, see if higher order functions like &lt;code&gt;filter&lt;/code&gt;/&lt;code&gt;map&lt;/code&gt;/&lt;code&gt;reduce&lt;/code&gt; can be used. While this may not improve readability for all readers, it will improve your individual skillset.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;Want more tips?&lt;/strong&gt; This practice is taken from &lt;a href="https://basecodefieldguide.com"&gt;BaseCode&lt;/a&gt; - a field guide containing 10 real-world practices to help you improve the code you write every day.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>practices</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Removing Comments</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Thu, 15 Feb 2018 13:45:26 +0000</pubDate>
      <link>https://dev.to/gonedark/removing-comments--204k</link>
      <guid>https://dev.to/gonedark/removing-comments--204k</guid>
      <description>&lt;p&gt;After my post on &lt;a href="https://dev.to/gonedark/are-you-a-boy-scout-b9"&gt;Boyscouting&lt;/a&gt; I found most of the discussion focused on code comments. Specifically, that part of boyscouting was &lt;em&gt;removing&lt;/em&gt; comments. Tips on removing comments was also one of my most popular &lt;a href="https://twitter.com/i/moments/948577473742233600"&gt;code cleanup tweets&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Recently removing comments came up again in a code review:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// filter out contacts that have unsubscribed
$contacts = $unsubscribedFilter-&amp;gt;filter($contacts);

// filter out duplicate contacts
$contacts = $duplicateFilter-&amp;gt;filter($contacts);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The reviewer asked why I "&lt;em&gt;removed the documentation&lt;/em&gt;" when I condensed the code to:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$contacts = $unsubscribedFilter-&amp;gt;filter($contacts);
$contacts = $duplicateFilter-&amp;gt;filter($contacts);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I'll come back to the difference between &lt;em&gt;comments&lt;/em&gt; and &lt;em&gt;documentation&lt;/em&gt;. For now, there is a difference and what I removed were indeed comments.&lt;/p&gt;

&lt;p&gt;First, let me acknowledge all the team leads and enginering managers crying out:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remove Comments?!!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, I am suggesting removing comments from your code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Surely you don't mean removing useful comments?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, what's a &lt;em&gt;useful&lt;/em&gt; comment?&lt;/p&gt;

&lt;p&gt;Let's back up and address the distiction between &lt;em&gt;comments&lt;/em&gt; and &lt;em&gt;documentation&lt;/em&gt;. Documentation is formatted comment blocks (e.g. DocBlock, JavaDoc, etc). Comments are everything else.&lt;/p&gt;

&lt;p&gt;A comment should relay &lt;strong&gt;why&lt;/strong&gt;, not &lt;em&gt;what&lt;/em&gt; or &lt;em&gt;how&lt;/em&gt;. Said another way, if there is something that can't be relayed by reading the code, then a comment might be needed.&lt;/p&gt;

&lt;p&gt;Going back to the code review, there was nothing the comments relayed that the code did not. I can infer from the assignment and method names we are "&lt;em&gt;filtering duplicate contacts&lt;/em&gt;". So the code comment above is &lt;strong&gt;not&lt;/strong&gt; useful. In fact, I wasted time reading it.&lt;/p&gt;

&lt;p&gt;For me, removing comments is about acheiving code that clearly communicates. One could even refactor the code to improve readability. Consider:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$contacts-&amp;gt;filterUnsubscribed();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Comments can not only be useful, they can also be misleading. I continually come across outdated comments that have not evolved as the code has changed. I recently needed to fix the following legacy code which was prematurely ending.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;foreach ($items as $item) {
    if ($item-&amp;gt;published) {
        // we've hit the most recent item before this push, so stop looping
        exit;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The comment says to stop looping, but the code exits. I wasted several minutes debating which to trust. Given the bug, I updated the code to follow the comment and &lt;em&gt;stop looping&lt;/em&gt;. Regardless, this bug would have been solved without the comment. Combined with the buggy code, it did more harm than good.&lt;/p&gt;

&lt;p&gt;That's really what it's about – doing good. Leaving something better than you found it. That's why it's called &lt;a href="http://jason.pureconcepts.net/2015/01/are-you-a-boy-scout/"&gt;Boyscouting&lt;/a&gt;. If you come across a comment that you can remove, remove it. If you can't remove it, see if you can refactor the code so you can remove the comment. Future developers will thank you. Even if that future developer is you.&lt;/p&gt;

&lt;p&gt;I eventually came across the following passage from &lt;a href="https://twitter.com/rob_pike"&gt;Rob Pike&lt;/a&gt; regarding comments which, quite effectively, summarizes this entire post.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[comments are] a delicate matter, requiring taste and judgment. I tend to err on the side of eliminating comments, for several reasons. First, if the code is clear, and uses good type names and variable names, it should explain itself. Second, comments aren’t checked by the compiler, so there is no guarantee they’re right, especially after the code is modified. A misleading comment can be very confusion. Third, the issue of typography: comments clutter code.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;Want more cleanup tips?&lt;/strong&gt; I'm writing a "field guide" with real-world practices to help you write code that truly lasts. &lt;a href="https://basecodefieldguide.com"&gt;Sign up&lt;/a&gt; for early access.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>refactoring</category>
      <category>practices</category>
    </item>
    <item>
      <title>Practicing YAGNI - Show me the code</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Mon, 29 Jan 2018 18:08:43 +0000</pubDate>
      <link>https://dev.to/gonedark/practicing-yagni---show-me-the-code-pjn</link>
      <guid>https://dev.to/gonedark/practicing-yagni---show-me-the-code-pjn</guid>
      <description>&lt;p&gt;After my &lt;a href="https://dev.to/gonedark/practicing-yagni-3n1d"&gt;Practicing YAGNI&lt;/a&gt; post, many asked to see what practicing YAGNI looks like &lt;em&gt;in code&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As a quick recap - YAGNI is a principle of &lt;a href="http://www.extremeprogramming.org/"&gt;eXtreme Programming&lt;/a&gt;. YAGNI is an acronym for You Aren't Gonna Need It.&lt;/p&gt;

&lt;p&gt;I think Ron Jeffries, one of the co-founders of eXtreme Programming, summarizes practicing YAGNI well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implement things when you actually need them, never when you just foresee that you need them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Practicing YAGNI is hard
&lt;/h2&gt;

&lt;p&gt;Despite the fun acronym and straightforward summary, programmers often succumb to over-engineering, implementing new shiny tech, or adding additional features. Even if we overcome these urges, it's still unclear what practicing YAGNI means in code. After all, we're programmers and code speaks louder than words.&lt;/p&gt;

&lt;p&gt;Rasmus Lerdof said to me once, &lt;em&gt;"Show me the code"&lt;/em&gt;. So I'm going to spend the rest of this article working through a series of &lt;a href="https://www.mountaingoatsoftware.com/agile/user-stories"&gt;stories&lt;/a&gt;. By practicing YAGNI, we'll see how the code evolves naturally, not inherently. These code samples are written in PHP to honor Mr. Lerdof.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Story
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As&lt;/em&gt; marketing I want to get a list of all users so I can perform analytics.&lt;br&gt;
&lt;em&gt;Given&lt;/em&gt; I access a specific URL&lt;br&gt;
&lt;em&gt;Then&lt;/em&gt; I should get a list of all users in JSON format&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first story is the most challenging. This is when our urges are the greatest. Remember, YAGNI tells us to only implement what we actually need. Or, said another way, write the simplest thing possible.&lt;/p&gt;

&lt;p&gt;Here is what that code might look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$mysqli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;mysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbpass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbname'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SELECT * FROM users'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fetch_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MYSQLI_ASSOC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Admittedly this code is not elegant. It'll probably get you down voted on Reddit or StackOverflow. &lt;a href="https://pragprog.com/book/tpp/the-pragmatic-programmer"&gt;The Pragmatic Programmer&lt;/a&gt; discusses writing &lt;em&gt;"Good Enough Software"&lt;/em&gt;, and that's exactly what this is. At just 7 lines of code it's undeniably simple. Any junior programmer can readily work with the code. Most importantly, it completes the story. Nothing more. Nothing less (well, technically, we could have dumped the &lt;code&gt;users&lt;/code&gt; table in JSON format and served a static file).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Second Story
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As&lt;/em&gt; legal I don't want the user's password to be in the response so we don't get sued.&lt;br&gt;
&lt;em&gt;Given&lt;/em&gt; I access the URL for the user list&lt;br&gt;
&lt;em&gt;Then&lt;/em&gt; I should get a list of all users in JSON format&lt;br&gt;
&lt;em&gt;And&lt;/em&gt; it should not include their password&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So what's the simplest thing we can possibly do? Well we can adjust the SQL query to only select the &lt;em&gt;appropriate&lt;/em&gt; fields.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$mysqli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;mysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbpass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbname'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SELECT email, role FROM users'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fetch_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MYSQLI_ASSOC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Third Story
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As&lt;/em&gt; marketing I want to filter the user list by email address so I can group user data more easily.&lt;br&gt;
&lt;em&gt;Given&lt;/em&gt; I access the URL for the user list&lt;br&gt;
&lt;em&gt;And&lt;/em&gt; I set an "email" parameter&lt;br&gt;
&lt;em&gt;Then&lt;/em&gt; I should get a list of all users in JSON format whose email address contains the "email" parameter value&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Again, let's adjust the SQL query based on the &lt;code&gt;email&lt;/code&gt; parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$mysqli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;mysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbpass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbname'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SELECT email, role FROM users'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'WHERE email LIKE \'%'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'%\''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fetch_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MYSQLI_ASSOC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, while this completes the story, there are a few things we should not continue to ignore.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Increased complexity&lt;/strong&gt;. The &lt;code&gt;if&lt;/code&gt; statement introduces a new logical branch of the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate of change&lt;/strong&gt;. Each of the recent stories has required changing the SQL statement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security risk&lt;/strong&gt;. The added code is vulnerable to SQL injections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These reasons should guide us to refactor our code. A common misconception is YAGNI and refactoring oppose one another. I find their relationship to be more symbiotic. YAGNI keeps my code simple, which makes it easy to refactor. If my code is easy to refactor, then I may quickly rework the code at any time. This gives me confidence to continue writing simple code and perpetuate the cycle.&lt;/p&gt;

&lt;p&gt;So, let's refactor to extract the complexity. Being more familiar with the code at this point, a &lt;em&gt;Repository&lt;/em&gt; object is an obvious candidate. In addition, we'll also ensure the Repository mitigates our risk of SQL injection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$mysqli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;mysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbpass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbname'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$userRepository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Fourth Story
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As&lt;/em&gt; marketing I want to see a description for "role" so I can better understand the data.&lt;br&gt;
&lt;em&gt;Given&lt;/em&gt; I access the URL for the user list&lt;br&gt;
&lt;em&gt;And&lt;/em&gt; the user's role is 1 or 2&lt;br&gt;
&lt;em&gt;Then&lt;/em&gt; I should see "Member" or "VIP" (respectively) for "role"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are multiple implementations available, two quickly come to mind. We can implement this in the SQL statement or we could implement this with code. While updating the SQL statement is arguably the simplest, it dramatically increases its complexity. For this reason, I chose to implement this with code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$mysqli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;mysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbpass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbname'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$raw_users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$userRepository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$raw_users&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="s1"&gt;'role'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'role'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'VIP'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Member'&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code works, however just as before it introduces new code branches and business logic. It also doubles our line count. So, I'll use some of the time I saved writing this simple solution to see if there's a more straightforward option. Indeed there is, PHP has a &lt;code&gt;JsonSerializable&lt;/code&gt; interface we can implement to return a value to &lt;code&gt;json_encode()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I can introduce a simple &lt;code&gt;User&lt;/code&gt; object which implements &lt;code&gt;JsonSerializable&lt;/code&gt; and move the new logic there. I'll update &lt;code&gt;UserRepository&lt;/code&gt; to return an array of &lt;code&gt;User&lt;/code&gt; objects. The final code is the same as when I started the story, proving a successful refactor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$mysqli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;mysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbpass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbname'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$userRepository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Fifth Story
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;As&lt;/em&gt; Finance I need to get the user list in XML format so we can import it into our archaic systems.&lt;br&gt;
&lt;em&gt;Given&lt;/em&gt; I access the URL for the user list&lt;br&gt;
&lt;em&gt;And&lt;/em&gt; I set my "Accept" header to "application/xml"&lt;br&gt;
&lt;em&gt;Then&lt;/em&gt; I should get a list of all users in XML format&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You're getting the hang of this now, so let's just add some &lt;code&gt;if&lt;/code&gt; statements to vary the response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$mysqli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;mysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbpass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbname'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$userRepository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;strpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'HTTP_ACCEPT'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'application/xml'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/xml'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// output the XML...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could continue down this path, but we would reintroduce code branches. If you were test driving this code with &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt; (another key XP principle) you might have noticed this while adding contexts to test the different code paths. So let's use this opportunity to introduce an object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$mysqli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;mysqli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbpass'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'dbname'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$mysqli&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$userRepository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nc"&gt;ContentNegotiator&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sendResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case a simple content negotiator we pass the user data to. It might even be static as it has no state and simply outputs a response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retro
&lt;/h2&gt;

&lt;p&gt;Let's take a look at what practicing YAGNI afforded us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt;. We completed 5 stories quickly and easily as YAGNI kept us focused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;. We actually decreased the size of the initial code. We introduced new objects as they were needed, improving their cohesion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stress-free&lt;/strong&gt;. Finally, we achieved all this without stress. We didn't get "stuck" worrying about the architecture or scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully you find the same benefits from practicing YAGNI as I have.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;Want more?&lt;/strong&gt; Follow &lt;a href="https://twitter.com/gonedark"&gt;@gonedark&lt;/a&gt; on Twitter to get weekly coding tips, resourceful retweets, and other randomness.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>practices</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Practicing YAGNI</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Wed, 17 Jan 2018 16:05:48 +0000</pubDate>
      <link>https://dev.to/gonedark/practicing-yagni-3n1d</link>
      <guid>https://dev.to/gonedark/practicing-yagni-3n1d</guid>
      <description>&lt;p&gt;A while back I spoke at &lt;a href="http://laracon.us/" rel="noopener noreferrer"&gt;Laracon&lt;/a&gt; about &lt;em&gt;Practicing YAGNI&lt;/em&gt;. It was an honor to present in front of such a large audience at such a premiere conference. To this day, I continue to receive a lot of feedback and interest in my talk.&lt;/p&gt;

&lt;p&gt;To that point, many have asked me to share my slides. As the slides were mostly placeholders for discussion, I felt a blog post would better summarize the talk. Nevertheless, if you want to see the slides, you can watch my talk on &lt;a href="https://streamacon.com/video/laracon-us/jason-mccreary-yagni-with-laravel" rel="noopener noreferrer"&gt;StreamACon&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;I consider myself a searcher. On a quest to find the &lt;em&gt;Holy Grail&lt;/em&gt; of programming practices - that single practice which instantly levels up my skills. While I know this doesn't exist, I do believe in a set of practices. Recently, I found one to be &lt;em&gt;YAGNI&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;YAGNI is a principle of &lt;a href="http://www.extremeprogramming.org" rel="noopener noreferrer"&gt;eXtreme Programming&lt;/a&gt; - something I practice daily &lt;a href="http://jason.pureconcepts.net/2015/05/two-weeks-extreme-programming/" rel="noopener noreferrer"&gt;at work&lt;/a&gt;. YAGNI is an acronym for &lt;em&gt;You Aren't Gonna Need It&lt;/em&gt;. It states a programmer should not add functionality until deemed necessary. In theory, this seems straightforward, but few programmers practice it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why practicing YAGNI is hard
&lt;/h2&gt;

&lt;p&gt;Before we continue talking about YAGNI, we need to understand the problem it solves. The problem is &lt;em&gt;over engineering&lt;/em&gt;. At some point, we started priding ourselves on complexity - obsessed with playing design pattern bingo and building ever more intricate architectures in our head.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xkcd.com" rel="noopener noreferrer"&gt;XKCD&lt;/a&gt; illustrates over engineering well with &lt;em&gt;"The General Problem"&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%2Fibqvmxh12log51uv2e16.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%2Fibqvmxh12log51uv2e16.png" alt="The General Problem" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is funny because it's true. But it begs the question - why can't we just pass the salt?&lt;/p&gt;

&lt;p&gt;What ever happened to &lt;a href="https://en.wikipedia.org/wiki/KISS_principle" rel="noopener noreferrer"&gt;KISS&lt;/a&gt;? What's wrong with an &lt;a href="https://en.wikipedia.org/wiki/Minimum_viable_product" rel="noopener noreferrer"&gt;MVP&lt;/a&gt;? The answer is &lt;em&gt;nothing&lt;/em&gt;. We need to find our way back to simple. YAGNI can help us get there.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to practice YAGNI
&lt;/h2&gt;

&lt;p&gt;I think Ron Jeffries, one of the co-founders of eXtreme Programming, summarizes practicing YAGNI well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implement things when you actually need them, never when you just foresee that you need them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nonetheless, the most common contention is &lt;em&gt;timing&lt;/em&gt;. We continually write code sooner than we &lt;em&gt;actually need&lt;/em&gt; them. This is the over-engineer in us. We confuse &lt;em&gt;foreseeing&lt;/em&gt; with &lt;em&gt;needing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To help distinguish between the two, we can create a time horizon. Kent Beck describes this well during an interview on &lt;a href="http://www.fullstackradio.com" rel="noopener noreferrer"&gt;Full Stack Radio&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;…I did a little experiment… what if I deliberately stopped trying to predict the future and limit my design horizon to six months… things went better for me… I was less over engineering. I was making progress sooner. I was less anxious… Things were cleaner, easier to understand… So what about three months? One month? I never reached a limit with that experiment…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this way, practicing YAGNI becomes a time experiment. One where we keep decreasing our time horizon to help limit the code we write. Ideally until we reach a point where we don't write code until it's actually needed. Not just because we're thinking about it, or want to, or it relates to code we're working on. We wait until the current code &lt;em&gt;requires&lt;/em&gt; us to implement new code in order to work.&lt;/p&gt;

&lt;p&gt;At first, I'll admit, this will feel like laziness. It's going to seem like you're intentionally avoiding writing code. In a way, this is true. The catch is, the code you're &lt;em&gt;wanting&lt;/em&gt; to write isn't ready to be written. By waiting, you prevent all the bad things that happen when you make assumptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  When not to practice YAGNI
&lt;/h2&gt;

&lt;p&gt;Once you realize the benefits of YAGNI, you're going to try to apply it to everything (another programmer curse). You need to remember with great power, comes great responsibility. YAGNI isn't about &lt;em&gt;saying no&lt;/em&gt;. YAGNI is about deferring unnecessary complexity.&lt;/p&gt;

&lt;p&gt;As such, there will be times when you should not call YAGNI. Unfortunately, this takes experience. So I will outline a few scenarios to help those getting started.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning something new:&lt;/strong&gt; You should take the time when evaluating a new technology. You'll gain the time back later, and mitigate the risk of losing more time by making the wrong decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current design decisions based on future needs:&lt;/strong&gt; YAGNI shouldn't handicap or sabotage our efforts. In these scenarios, make the future-proof design decision, but only implement enough to fulfill the current need. This allows us to limit rework, without completely undermining YAGNI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Abstracting external dependencies:&lt;/strong&gt; External dependencies add complexity to your project. Inline with the previous examples, taking the time to abstract these dependencies will avoid rework and decrease the complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing, Security, Scale, and Business Requirements:&lt;/strong&gt; Sorry, but YAGNI is not a free-pass on writing tests, secure code, considering scale, or business requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What YAGNI means to me
&lt;/h2&gt;

&lt;p&gt;Practicing YAGNI gives me confidence. I am comfortable delaying design decisions because I will be better informed in the future. I trust my ability to pivot quickly because my code is simple, making it easy to refactor and evolve. I write less code, and let's be honest, the best code is &lt;em&gt;no&lt;/em&gt; code.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;Want more?&lt;/strong&gt; Follow &lt;a href="https://twitter.com/gonedark" rel="noopener noreferrer"&gt;@gonedark&lt;/a&gt; on Twitter to get weekly coding tips, resourceful retweets, and other randomness.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>practices</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>2018 Dev Goals</title>
      <dc:creator>Jason McCreary</dc:creator>
      <pubDate>Mon, 08 Jan 2018 13:46:03 +0000</pubDate>
      <link>https://dev.to/gonedark/2018-dev-goals-4abd</link>
      <guid>https://dev.to/gonedark/2018-dev-goals-4abd</guid>
      <description>&lt;p&gt;At the beginning of each new year set goals. While I split them between personal and professional goals, I find the lines can blur. I like what I do. So, even though these are my goals as a professional developer, they are personal goals too.&lt;/p&gt;

&lt;p&gt;Here are my goals for 2018:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write a book&lt;/li&gt;
&lt;li&gt;Learn Python&lt;/li&gt;
&lt;li&gt;Expand Shift services&lt;/li&gt;
&lt;li&gt;Speak at 5 conferences&lt;/li&gt;
&lt;li&gt;Reach 10k Twitter followers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d like to go through them. Not just to explain the goals, but the motivation behind them. In doing so, they may help you set a few goals of your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write a book
&lt;/h2&gt;

&lt;p&gt;I never planned on writing a book. Despite writing hundreds of blog posts, dozens of magazine articles, and several talks I never thought I had enough material to fill a whole book. I love sharing my experiences. It’s the motivation for all the writing I do.&lt;/p&gt;

&lt;p&gt;Back in November I started sharing &lt;a href="https://twitter.com/i/moments/948577473742233600"&gt;code cleanup tips on Twitter&lt;/a&gt;. Each week, I’d share a tip to cleanup your code. Each week, the tweets received more retweets and more likes. Some well into the hundreds. It’s funny as the whole thing started as a bit of a challenge. I was bored in a meeting and &lt;a href="https://twitter.com/gonedark/status/918478994957307905"&gt;asked developers&lt;/a&gt; to send a code snippet they wanted cleaned up.&lt;/p&gt;

&lt;p&gt;Even with all these positive responses and ensuing discussion, I still never thought I had material to write a book. After all, how do you take a bunch of tweets and turn them into a book. I mean you don’t. What you can turn them into is a &lt;em&gt;field guide&lt;/em&gt; - a short book with pragmatic practices to improve the code you write every day.&lt;/p&gt;

&lt;p&gt;With my birthday at the end of the month, I realized that I've been programming for 20 years. It was this realization that was actually the deciding factor. In the developer world, that’s a lifetime of experiences working with dozens of development teams, developing hundreds of projects, and writing thousands of lines of code. Combining my experience with my tweets to provide backstory and motivation for writing cleaner code in the real world felt like enough. So I am writing &lt;a href="https://basecodefieldguide.com/"&gt;BaseCode - a field guide to lasting code&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn Python
&lt;/h2&gt;

&lt;p&gt;Learning a new language a year was actually suggested to me as a &lt;a href="https://jason.pureconcepts.net/2009/12/good_developer_routines/"&gt;good routine&lt;/a&gt; by a TA in college.&lt;/p&gt;

&lt;p&gt;However, development has changed. Especially web development. When I first started knowing HTML was enough. Then it was HTML, CSS, and JavaScript. Now it's so much more. You have to learn &lt;em&gt;languages&lt;/em&gt;, &lt;em&gt;frameworks&lt;/em&gt;, &lt;em&gt;APIs&lt;/em&gt;, and all the tools in between.&lt;/p&gt;

&lt;p&gt;Technically speaking, the last language I learned was Swift. That was a few years ago. So I’m overdue. This year, I chose Python. There’s no requirement for me to learn Python. At least not for my career. I chose it because it seems to have a place in data analytics.&lt;/p&gt;

&lt;p&gt;Investing is my second passion. I’m always looking for ways to combine my two passions of programming and investing. What better way than to analyze my trading habits with a few Python scripts. Who knows, maybe I’ll end up with an algorithm that outperforms the market and I'll start an investment firm. That's pretty unlikely, but at least I know Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expand Shift Services
&lt;/h2&gt;

&lt;p&gt;Two years ago I created &lt;a href="https://laravelshift.com"&gt;Laravel Shift&lt;/a&gt;. It provides automated and human services for upgrading Laravel, Lumen, and PHP projects between major versions.&lt;/p&gt;

&lt;p&gt;Shift has been a great side project. But I’m at a critical point where it needs work to get to the next level. Otherwise, it will likely stagnate, rot, and die. An all too common tale and one that I’ve lived before with &lt;a href="https://jason.pureconcepts.net/2014/03/successful-app-fail/"&gt;another side project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I don’t want to see that happen to Shift. The goal this year will be to focus the core platform by cutting some of the services that don’t generate revenue and instead put that effort into expanding to new markets - either other sub communities within PHP or even other languages like JavaScript or Ruby.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speak at 5 conferences
&lt;/h2&gt;

&lt;p&gt;Over the past few years I’ve been fortunate to make the transition from a conference attendee to a conference speaker. As I mentioned before, I love sharing my experiences. Seeing an audience engage, share, and grow during one of my talks has been incredibly rewarding.&lt;/p&gt;

&lt;p&gt;This year I hope to increase the number of conference engagements. I’m well on the way to achieving my goal as my talks have already been accepted to 3 conferences. I expect to reach this goal, so I created a sub goal - I’d like to be a keynote speaker or speak at a new conference. Maybe one that is not even tech related.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reach 10k Twitter followers
&lt;/h2&gt;

&lt;p&gt;This goal is pretty straightforward. However, the motivations are not. It’s a means to an end. That end, for me, is &lt;em&gt;reach&lt;/em&gt;. I’m not talking about being popular. Again, it's about sharing my experiences in an effort to teach. Every teacher needs an audience.&lt;/p&gt;

&lt;p&gt;Reaching &lt;a href="https://twitter.com/gonedark"&gt;10,000 followers on Twitter&lt;/a&gt; accomplishes two things. First, it’s positive feedback that people find value in what I am sharing. Second, it allows me to reach an audience more directly. Let me elaborate on this a bit.&lt;/p&gt;

&lt;p&gt;Unless you’re inherently famous or virally fortunate, you have to grow your audience. You have to write blog posts, speak at conferences, and make things. Then you have to share all that carefully and meticulously. You have to ask people to share your stuff. It’s an awkward, relentless push. All that might get you a few thousand followers.&lt;/p&gt;

&lt;p&gt;Maybe at 10k followers it might be a little easier to my experiences with a large enough core audience to make an impact.&lt;/p&gt;




&lt;p&gt;I hope these insights into my own goals help you create some of your own. Tech is constantly in motion. Keeping up is the minimum requirement. Goals are a great way to ensure you’re not just keeping up, but accelerating.&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
