<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Soluto Nashville - Medium]]></title>
        <description><![CDATA[As technology evolves, so does the complexity of making it all work. Soluto is focused on helping our 45 million customers solve this problem. www.SolutoNashville.com - Medium]]></description>
        <link>https://medium.com/soluto-nashville?source=rss----4da90db368ce---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Soluto Nashville - Medium</title>
            <link>https://medium.com/soluto-nashville?source=rss----4da90db368ce---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 09:20:51 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/soluto-nashville" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Cleaning up your crime scene of a pull request]]></title>
            <link>https://medium.com/soluto-nashville/cleaning-up-your-crime-scene-of-a-pull-request-72e007f8bd20?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/72e007f8bd20</guid>
            <category><![CDATA[pull-request]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[git]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[github]]></category>
            <dc:creator><![CDATA[Reece Boyd]]></dc:creator>
            <pubDate>Wed, 08 Apr 2020 19:27:57 GMT</pubDate>
            <atom:updated>2020-04-08T19:30:32.388Z</atom:updated>
            <content:encoded><![CDATA[<h3>Clean up your crime scene of a pull request</h3><p>A few git commands to help you get away with the murder of your codebase</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xzslZuVylH6Pcjrj" /><figcaption>“There was a struggle”</figcaption></figure><p>Congrats on getting your code to work! But you’re not done yet. Developers of today will drop what they are working on to review your code. Developers of tomorrow will review your code to understand how something works. Here are simple steps to clean up your code and make it painless for your victims — I mean peers:</p><p><strong>Are your commits like a crime scene? Do they reveal a struggle between you and the code?</strong></p><pre>git fetch &amp;&amp; git reset —-soft origin/master</pre><p>will take all of your commits that are different than what we would presumably have running in PROD and move them back to staging.</p><p>If you have been doing a lot of trial and error, do and undo type commits, this can be a one command cleanup. Just recommit 1 pretty commit that looks like you didn’t even struggle.</p><p><strong>Is your PR doing too much? (Apply the Single-Responsibility Principle to PRs)</strong></p><p>The previous command can also be useful if you decide your PR accomplishes 3 things and should therefore be 3 PRs instead of 1. Now that your changes are back in staging, you can easily make 3 neat commits and cherry-pick these commits out to their own branch, like so:</p><pre>git checkout -b branch-for-commit-1</pre><pre>git cherry-pick &lt;commit SHA for commit 1&gt;</pre><pre>git push #push that branch up to origin so you can make a PR</pre><p>Repeat for commits 2 and 3.</p><p><strong>Different crimes, different measures:</strong></p><p>Want to combine the last 2 or 3 commits instead of ALL of the differences between your branch and master?</p><pre>git fetch &amp;&amp; git reset —-soft HEAD~2 # or 3 or w/e # you want</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=72e007f8bd20" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/cleaning-up-your-crime-scene-of-a-pull-request-72e007f8bd20">Cleaning up your crime scene of a pull request</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Be a Polyglot Software Engineer?]]></title>
            <link>https://medium.com/soluto-nashville/why-be-a-polyglot-software-engineer-29cf53465d15?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/29cf53465d15</guid>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Ithamar Diaz]]></dc:creator>
            <pubDate>Mon, 22 Oct 2018 19:26:15 GMT</pubDate>
            <atom:updated>2018-10-22T19:26:15.199Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gmylU8o9WD9vwxrw" /><figcaption>Photo by <a href="https://unsplash.com/@markusspiske?utm_source=medium&amp;utm_medium=referral">Markus Spiske</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>A polyglot is a person who speaks many languages, therefore a polyglot software engineer is a person who writes software with many programming languages. It might be tempting to box yourself into a single language in hopes of attaining mastery. But pursuing the path of a polyglot is far more rewarding. It puts you in an advantageous position and helps you build a more resilient skill set.</p><h3>It reinforces the basics.</h3><p>At some point in a software engineer’s career, they’ll be asked to rapidly switch gears and work with an unfamiliar language. Luckily, having a good understanding of programming concepts speeds up the process of learning a new language. Programming concepts are shared between languages, so seeing these concepts in other languages will reinforce them. For example, if you learn about looping or flow control concepts in one language, you‘ll see familiar concepts in other languages, as well.</p><h3>It helps you tackle more problems.</h3><p>A software engineer who better understands all programming paradigms can tackle difficult problems. For example, some problems might be easier to solve using a declarative language over an imperative language. Learning languages from each paradigm will help you learn more about the paradigms themselves.</p><h3>It improves your current languages.</h3><p>Studying different languages can pinpoint your strengths and weaknesses in the languages you already know. Sometimes new languages are created because particular tasks were too difficult in an existing language, studying how the new language approached that particular task could help you approach the same tasks in the languages you already know. To be considered proficient, a software engineer must produce functioning software that’s also syntactically idiomatic and easy for others to maintain and understand. To be a polyglot software engineer, you should be at least proficient in the languages you choose to learn. Achieving proficiency in a language can be done in a shorter amount of time than mastering a language and will allow the engineer to learn more languages.</p><h3>It makes you a jack-of-all-trades.</h3><p>A polyglot software engineer is versatile team member, and the industry values that versatility. Often polyglots have not mastered a language, and that’s okay. Languages and frameworks will come and go, but programing concepts and computer science theory sticks around. An engineer who’s well versed in programing concepts and computer science theorems, plus proficient in different languages, is building a desirable skill set.</p><h3>It helps you adapt code examples.</h3><p>An engineer proficient in many languages should be able to adapt code examples to another language. When using a library or an API, the code examples might be in a language an engineer doesn’t know. But as a polyglot software engineer, you might be able to adapt those examples because of your exposure to similar languages and knowledge of different programming paradigms.</p><h3>How to become a polyglot software engineer.</h3><ol><li>Pick a language to learn from a paradigm you haven’t learned. Below is a non-exhaustive list of paradigms and some example languages for that paradigm.<br><strong>Declarative</strong>: SQL , Prolog<br><strong>Object Oriented</strong>: Scala, Java, C++, Ruby<br><strong>Functional</strong>: Clojure, Haskell, Elixir, AsmL<br><strong>Event-driven</strong>: Javascript, Visual Basic<br><strong>Procedural</strong>: Lisp, Python<br><strong>Imperative</strong>: C, C++, Java<br><strong>Multi-paradigm</strong>: Perl</li><li>Complete a tutorial. Everyone learns differently and there are a different ways to complete tutorials for the chosen language. Youtube tutorial videos, tutorial websites, technical tutorials on blogs, etc. My favorite way to learn a new language is through koans, fixing broken tests written in the chosen language. Be patient, it might be difficult. Look for the programming language concepts you already know and see if you can find them in the chosen language. If you need more help find a forum for the language or join the subreddit for the language.<br><a href="http://rubykoans.com/">Ruby Koans</a><br><a href="http://clojurekoans.com/">Clojure Koans</a><br><a href="https://github.com/liammclennan/JavaScript-Koans">Javascript Koans</a><br><a href="https://github.com/butlermatt/dart_koans">Dart Koans</a><br><a href="https://github.com/matyb/java-koans">Java Koans</a></li><li>Write a working piece of software in the chosen language. To help with motivation, focus on something you are already interested in and write software related to that interest. The software doesn’t have to be the next big startup, just complicated enough to try to use more than just the basics of the language. This step will help you get closer to being proficient with the language.</li><li>Contribute to an open source project that uses that chosen language. Do not skip this step as it will force you to have to write code in the chosen language that should be maintainable by other people. If you aren’t using the chosen language at work, then you will not have an easy way to know if you are writing maintainable code.</li><li>Repeat step one.</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=29cf53465d15" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/why-be-a-polyglot-software-engineer-29cf53465d15">Why Be a Polyglot Software Engineer?</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Best Security Practices for Amazon RDS with Sequelize]]></title>
            <link>https://medium.com/soluto-nashville/best-security-practices-for-amazon-rds-with-sequelize-600a8b497804?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/600a8b497804</guid>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[amazon-web-services]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[security]]></category>
            <dc:creator><![CDATA[Brandon Evans]]></dc:creator>
            <pubDate>Fri, 07 Sep 2018 18:43:17 GMT</pubDate>
            <atom:updated>2019-04-26T19:38:42.191Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mZRAfKrWwinnPD7PxZxRlQ.jpeg" /></figure><p>About a year ago, our team at <a href="https://www.solutonashville.com/">SolutoNashville</a> started working with <a href="https://aws.amazon.com/rds/">Amazon RDS</a>. It allows you to use several popular relational database dialects without having to manage hardware, run a server, or perform manual backups, among many other things. Our application connects to RDS using Node.js on <a href="https://aws.amazon.com/lambda/">AWS Lambda</a>.</p><p>As Soluto and the rest of <a href="https://www.asurion.com/">Asurion</a> greatly value the security of our customer, contractor, and employee data, we insist on using end-to-end SSL/TLS for all of our systems. This means that, as information travels from a user’s computer to our backend APIs all the way to the database that powers them, nothing else can read or tamper with it.</p><p>Some may question the necessity to use end-to-end encryption for databases that aren’t publicly accessible from the internet. Although putting your instance in a VPC is strongly recommended, adding encryption can thwart insider attacks and mitigate damages if another system in your network is compromised.</p><p>In an age where a <a href="https://krebsonsecurity.com/2014/02/target-hackers-broke-in-via-hvac-company/">malware infected HVAC system at Target’s corporate headquarters can steal the credit card numbers of millions of its customers</a>, technology professionals should practice defense-in-depth and use all tools at their disposal to stay on their guard.</p><p>Our ORM of choice is <a href="http://docs.sequelizejs.com/">Sequelize</a>, a mature Node package that supports several dialects, including PostgreSQL and MySQL. Unfortunately, there’s not a lot of documentation for using it to connecting to databases securely, and RDS specifically poses additional challenges that required research from our team. In order to prevent you from going through the same troubles, here is how we established a secure connection to RDS.</p><h4>Establishing an Insecure Connection</h4><p>To start, let’s create an insecure connection to the database:</p><pre>const Sequelize = require(&#39;sequelize&#39;);</pre><pre>const sequelize = new Sequelize(dbname, username, password, {<br>    host: &#39;pgssltest.xxxxxxxxxxxx.region.rds.amazonaws.com&#39;,<br>    dialect: &#39;postgres&#39;<br>});</pre><p>This example uses PostgreSQL, but if you wanted to use MySQL, you could simply replace ‘postgres’ with ‘mysql’.</p><p>Once connected to the PostgreSQL database, if you have the <a href="https://www.postgresql.org/docs/current/static/sslinfo.html">sslinfo module</a> installed, you can perform the following query to verify whether or not you are using SSL/TLS:</p><pre>sequelize.query(&#39;select ssl_is_used()&#39;, { type: sequelize.QueryTypes.SELECT })<br>    .then((result) =&gt; {<br>        console.log(result[0].ssl_is_used);<br>    });</pre><p>With our current configuration, this will print “false” to the console. This means that, if a malicious device was on our network when we established this connection, it could read all database traffic, including the username and password.</p><p>For MySQL, you can use the following query to test SSL/TLS usage:</p><pre>sequelize.query(&quot;SHOW STATUS LIKE &#39;Ssl_cipher&#39;&quot;, { type: sequelize.QueryTypes.SELECT })<br>   .then((result) =&gt; {<br>       console.log(result[0].Value);<br>   });<br>}</pre><p>This will print nothing if SSL/TLS is not used and the cipher (Ex. DHE-RSA-AES256-SHA) otherwise. As expected, this prints nothing for the example above.</p><h4>Establishing a Secure Connection Without Verifying the Certificate</h4><p>Enabling SSL is as simple as setting a flag:</p><pre>const sequelize = new Sequelize(dbname, username, password, {<br>    host: &#39;pgssltest.xxxxxxxxxxxx.region.rds.amazonaws.com&#39;,<br>    dialect: &#39;postgres&#39;,<br>    dialectOptions: {<br>       ssl: true<br>    }<br>});</pre><p>If we execute select ssl_is_used() again, it will return true. However, this will not perform any validation of the server’s certificate. This means that, if the client’s DNS server was compromised, the hacker could direct the client to connect to its own SSL/TLS server, once again stealing the database credentials.</p><h4>Establishing a Secure Connection and Verifying the Certificate</h4><p>To reject invalid certificates, we simply need to set a dialect option like so:</p><pre>const sequelize = new Sequelize(dbname, username, password, {<br>    host: &#39;pgssltest.xxxxxxxxxxxx.region.rds.amazonaws.com&#39;,<br>    dialect: &#39;postgres&#39;,<br>    dialectOptions: {<br>        ssl: {<br>            rejectUnauthorized: true<br>        }<br>    }<br>});</pre><p>However, you should expect the following error:</p><pre>Unhandled rejection SequelizeConnectionError: self signed certificate in certificate chain</pre><p>For MySQL, you will get a similar error:</p><pre>Unhandled rejection SequelizeConnectionError: unable to get local issuer certificate</pre><p>To trust certificates that were signed by the AWS RDS certificate authority, first, download the <a href="https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem">RDS certificate bundle</a>. Then, load the certificate like so:</p><pre>const fs = require(&#39;fs&#39;);<br>const rdsCa = fs.readFileSync(__dirname + &#39;/rds-combined-ca-bundle.pem&#39;);</pre><p>Finally, supply the certificate authority in your constructor:</p><pre>const sequelize = new Sequelize(dbname, username, password, {<br>    host: &#39;pgssltest.xxxxxxxxxxxx.region.rds.amazonaws.com&#39;,<br>    dialect: &#39;postgres&#39;,<br>    dialectOptions: {<br>        ssl: {<br>            rejectUnauthorized: true,<br>            ca: [rdsCa]<br>        }<br>    }<br>});</pre><p>We are now back in business!</p><p>The MySQL module simplifies the process by providing an <a href="https://github.com/mysqljs/mysql#ssl-options">Amazon RDS profile</a>. To use it, you simply have to specify it like so:</p><pre>const sequelize = new Sequelize(dbname, username, password, {<br>    host: &#39;mysqlssltest.xxxxxxxxxxxx.region.rds.amazonaws.com&#39;,<br>    dialect: &#39;mysql&#39;,<br>    dialectOptions: {<br>        ssl: &#39;Amazon RDS&#39;<br>    }<br>});</pre><p>This will <strong>not</strong> work for PostgreSQL and will simply revert back to ignoring the validity of the certificate.</p><h4>Establishing a Secured Connection, Verifying the Certificate, and Using a CNAME</h4><p>We make it a practice to use create CNAMEs to point to our database instance URLs. This way, if we ever migrate environments or the database instance URL otherwise changes, we simply have to update the CNAME and can leave our clients alone.</p><p>If you are using the MySQL Amazon RDS profile, no modifications are necessary to use a CNAME. However, if you attempt to connect to a PostgreSQL database like so:</p><pre>const sequelize = new Sequelize(dbname, username, password, {<br>    host: &#39;pgssltest.mycname.com&#39;,<br>    dialect: &#39;postgres&#39;,<br>    dialectOptions: {<br>        ssl: {<br>            rejectUnauthorized: true,<br>            ca: [rdsCa]<br>        }<br>    }<br>});</pre><p>You will get the following error:</p><pre>Unhandled rejection SequelizeConnectionError: Hostname/IP does not match certificate&#39;s altnames: Host: pgssltest.mycname.com. is not cert&#39;s CN: pgssltest.xxxxxxxxxxxx.region.rds.amazonaws.com</pre><p>As the error implies, because the certificate provided by RDS contains a different domain name than your CNAME, it is treated as invalid. However, if your <a href="https://github.com/brianc/node-postgres">node-postgres</a> version 7.4.3 or higher, we can get around this issue like so:</p><pre>const tls = require(&#39;tls&#39;);</pre><pre>const sequelize = new Sequelize(dbname, username, password, {<br>    host: &#39;pgssltest.mycname.com&#39;,<br>    dialect: &#39;postgres&#39;,<br>    dialectOptions: {<br>        ssl: {<br>        rejectUnauthorized: true,<br>        ca: [rdsCa],<br>        checkServerIdentity: (host, cert) =&gt; {<br>            const error = tls.checkServerIdentity(host, cert);</pre><pre>            if (error &amp;&amp; !cert.subject.CN.endsWith(&#39;.rds.amazonaws.com&#39;)) {<br>                    return error;<br>                }<br>            }<br>        }<br>    }<br>});</pre><p>This will attempt to verify the certificate as usual, but if an error is thrown, and the certificate’s domain name ends in “.rds.amazonaws.com”, we will suppress the error and continue as normal.</p><h4>Bonus: Disable Insecure Connections</h4><p>Using SSL/TLS is great, but if other database clients don’t follow suit, you still have this security vulnerability. Fortunately, you can configure your database to reject insecure connections.</p><p>For PostgreSQL, we simply need to add a parameter group that has the setting rds.force_ssl set to 1. After application, if you attempt to connect to the database insecurely using Sequelize, you will get the following error:</p><pre>Unhandled rejection SequelizeConnectionError: no pg_hba.conf entry for host &quot;xxx.xxx.xxx.xxx&quot;, user &quot;pguser&quot;, database &quot;pgssltest&quot;, SSL off</pre><p>MySQL also has a similar parameter group setting called require_secure_transport, but unfortunately, it is not modifiable. Luckily, you can execute a query to have the same effect (See “Using SSL with a MySQL DB Instance” on <a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html">this page</a>). This will result in the following error for insecure connections:</p><pre>Unhandled rejection SequelizeAccessDeniedError: Access denied for user &#39;mysqluser&#39;@&#39;xxx.xxx.xxx.xxx&#39; (using password: YES)</pre><h4>Bonus: Encrypt Your Database</h4><p>At this point, all of your database traffic is encrypted in transit. Although this is an awesome step in the right direction, without encrypting your data at rest, it can still be compromised. You can follow <a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html">these steps</a> provided by AWS to ensure your resources are properly encrypted.</p><h4>Bonus: Disable Operator Aliases</h4><p>Although this isn’t specific to RDS, every Sequelize user should be familiar with the operatorAliases setting. To explain what it does, consider if we wanted to create a function that deletes a record with a specific ID:</p><pre>const deleteRecordById = async (recordId) =&gt; {<br>    return await models.Record.destroy({<br>        id: recordId<br>    });<br>}</pre><p>This works as expected. However, what if recordId is input from a user that wasn’t properly type-checked or otherwise validated? Imagine if recordId ended up being defined as:</p><pre>{<br>    $ne: &#39;fakeId&#39;<br>}</pre><p>This would result in the destroy call being evaluated like so:</p><pre>models.Record.destroy({<br>    id: {<br>        $ne: &#39;fakeId&#39;<br>    }<br>});</pre><p>With our current setup, this is interpreted as “delete every record that has an ID that is not equal to fakeId.” This would result in <strong>every record</strong> being deleted!</p><p>In this example, $ne is a string operator alias for [Op.ne]. Although we should have validated this input regardless, we can prevent strings from ever being interpreted as operator aliases by turning off the operatorAliases setting. That way, if we received the above input, the destroy call would be interpreted as “delete every record that has an ID that is equal to { $ne: &#39;fakeId&#39; },” which obviously wouldn’t match any records. For more information, see <a href="http://docs.sequelizejs.com/manual/tutorial/querying.html#operators-security">this section</a> of the Sequelize documentation.</p><p>With that change, our final Sequelize instantiation looks as follows:</p><pre>const sequelize = new Sequelize(dbname, username, password, {<br>    host: &#39;pgssltest.mycname.com&#39;,<br>    dialect: &#39;postgres&#39;,<br>    operatorsAliases: false,<br>    dialectOptions: {<br>        ssl: {<br>        rejectUnauthorized: true,<br>        ca: [rdsCa],<br>        checkServerIdentity: (host, cert) =&gt; {<br>            const error = tls.checkServerIdentity(host, cert);<br>if (error &amp;&amp; !cert.subject.CN.endsWith(&#39;.rds.amazonaws.com&#39;)) {<br>                    return error;<br>                }<br>            }<br>        }<br>    }<br>});</pre><p>Congratulations! Assuming you are not improperly reusing your database credentials, you are following best practices!</p><p>Remember, though, that this is not a silver-bullet, and you must ensure that the rest of your network and application are properly secured. This is the price we pay to earn the trust of our users, so keep on fighting the good fight!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=600a8b497804" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/best-security-practices-for-amazon-rds-with-sequelize-600a8b497804">Best Security Practices for Amazon RDS with Sequelize</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Adventures in Amazon Connect]]></title>
            <link>https://medium.com/soluto-nashville/adventures-in-amazon-connect-e26eefc2ecae?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/e26eefc2ecae</guid>
            <category><![CDATA[amazon]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[amazon-connect]]></category>
            <dc:creator><![CDATA[Lucas Rudd]]></dc:creator>
            <pubDate>Mon, 06 Aug 2018 15:53:33 GMT</pubDate>
            <atom:updated>2018-08-06T15:53:32.830Z</atom:updated>
            <content:encoded><![CDATA[<h4>Detailing the pros, cons, and all the “gotchas”</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/599/1*cPjqJ4S0bv2ZOdmG856eFA.png" /></figure><p>Here at <a href="http://www.solutonashville.com/">Soluto Nashville</a>, we work extensively with Amazon Web Services (AWS). Some of the most important work we’ve done in the past year has been with Amazon’s new cloud-based contact-center service, <a href="https://aws.amazon.com/connect/">Amazon Connect</a>.</p><p>With Amazon Connect being such a new service, there’s slim documentation available so we’ve had to learn many of the “gotchas” on our own through trial and error. In our experimental approach, we’ve seen both benefits and drawbacks along the way. Let’s take a look at some simplified use-cases to highlight what Connect has to offer and what it’s still lacking in its early stages.</p><p><em>Additional documentation can be found </em><a href="https://aws.amazon.com/documentation/connect/"><em>here</em></a><em>.</em></p><h3>The Basics</h3><h4>Contact Blocks</h4><p>Amazon Connect is a visual editing tool which outlines the logic needed to manage the experience a customer undergoes when calling into your place of business. Connect manages this experience in Contact Flow which must be be created and configured from the Amazon Connect console. These flows contain a variety of ‘Blocks,’ which are organized into five different categories (which Amazon refers to as Contact Blocks). These tools are generally standard among contact-center services–they allow for interactions with the customer, setting attributes/queues, and performing basic logical operations, among other things.</p><p>Although these tools are standard, the benefit of using Amazon Connect comes from being able to take advantage of the AWS ecosystem, using tools such as Lambda for integration and data manipulation, Lex for smart routing, and IAM roles for ensuring that these tools are only accessible from Connect.</p><p>One of Amazon Connect’s main benefits is its integration with AWS Lambda. This direct integration allows you to easily secure data operations through the use of generic or detailed function policies, as well as allows you to avoid exposing REST APIs that need to be secured. Lambdas can be configured to be triggered generically from any Amazon Connect contact flow, or can be more finely tuned to only allow integration from a single Amazon Connect instance using AWS Lambda function policies.</p><p>In order to begin directing calls to a Contact Flow hosted in Amazon Connect, you must first claim a number and link it to that Contact Flow. Pricing varies based on region, but is determined based on how many numbers associated with the Amazon Connect instance, as well as the length of time the customer was on the call.</p><h4>Example</h4><p>Here’s a simple example of what a Contact Flow may look like…</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*r9-RHxJuTBRVRbea" /><figcaption>A simple Contact Flow</figcaption></figure><p>This initially invokes an AWS Lambda function which retrieves information stored in ElastiCache about what types of issues the caller intent Lex bot understands. If successful, it saves the output to an attribute called ‘defaultSpeech;’ if it fails, a static value (in this case, it says ‘Please state your issue’) is set to the defaultSpeech attribute.</p><p>After the defaultSpeech attribute is set, the Lex Bot is then invoked. Depending on the customer’s vocalized input, the Lambda connected to the Lex Bot may take some additional actions on the backend. If/when the ‘PurposeIntent’ match is made, the response from the LexBot is saved in the ‘customerIntent’ attribute, and the customer is transferred to another Contact Flow for further processing.</p><p>If the customer indicates that they need help, the data stored in the ‘defaultSpeech’ attribute is read to the customer.</p><p>If the customer does not say something which matches one of the intents the Contact Flow is attempting to match, or at any point there is an error (or, if the customer indicates that they wish to speak to an agent) the working queue is set, and a reoccurring attempt is made to transfer the customer to the working queue specified until there is vacancy in that queue. If that attempted transfer happens to fail, the call is terminated, which is never ideal!</p><h4>User Management and Transfers</h4><p>Agents can be added and managed in Amazon Connect under the ‘User Management’ tab. Here, an agent’s login username, first and last name, email, security profile, routing profile and desk phone number can be managed.</p><p>The routing profile that an agent is assigned to indicates which queues they belong to, and what the priority of each of those queues are in relation to the routing profile. When you set a queue flow to transfer a customer to, the customer will be transferred to someone in the routing profile with that specified queue in the priority specified in the routing profile.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*V1M5Frh8Y8Wqyg9f" /><figcaption>An example of a routing profile for bilingual agents</figcaption></figure><p>When a call is transferred to a queue, agents who have a routing profile associated with that queue and who have an ‘Available’ status can receive the call on the phone number specified in their user profile. This number can either link to a desk-phone/handset, or a softphone; the agent can specify their status (such as ‘Available,’ ‘On Break,’ or other customized statuses) as well as take and transfer calls (among other things) through the Amazon Connect Contact Control Panel (CCP) which can be embedded in the application used by the call-center agents by using the Amazon Connect Streams API.</p><p>More information on the Amazon Connect Streams API and setting up the Amazon Connect CCP can be found in the Amazon Connect Streams <a href="https://github.com/aws/amazon-connect-streams">Github repository</a> and the <a href="https://docs.aws.amazon.com/connect/latest/userguide/agentconsole-guide.html">online documentation</a>.</p><h4>Security</h4><p>Additionally, integrating Amazon Connect with AWS Lambda and IAM roles allows you to transfer and manipulate customer information without stressing about securing your REST endpoints.</p><p>Although you should always consider security in your application, because the AWS Lambda invoked from Amazon Connect is set up with a policy to only accept requests from the particular Amazon Connect account in which this request originates, your requests are very safe compared to a similar REST call. There is no need to worry about securing publicly available endpoints from DDOS or injection attacks.</p><p>In addition to this, when you set up your Amazon Connect instance, you are able to set up how you want to manage your Amazon Connect users. These options allow you to manage users through SAML based authentication, link to an existing directory associated with your AWS account, or manage users in Amazon Connect directly (meaning, the managed users will have a username and password specific to Amazon Connect). This means that you can spend less time worrying about security, and more time focusing on the architecture of your application.</p><h3>Pain Points</h3><h4>Integration</h4><p>As of right now, Lambda is the only ‘integration’ tool that Connect provides; but, due to the flexible nature of AWS Lambda, you can do nearly anything imaginable with this single integration tool. Unfortunately, this means that you cannot integrate with REST APIs directly within the contact flow.</p><p>Although it is easy to set up a proxy Lambda to gather data from S3, DynamoDB, ElastiCache, etc. it would be nice to have the option to integrate directly with more of these services. In particular, I would like to see the ability to directly initiate a step function by ARN from Amazon Connect.</p><h4>Documentation</h4><p>The documentation on Amazon Connect is sparse. Due to this, some issues may arise which take much longer to diagnose than they should, leading to a lot of time lost on simple task. For example, it took us much longer than it should have to find diagnose that complex nested data objects are not yet supported in Amazon Connect. We were forced to find a work-around to such issues by flattening the data and using ‘dash’ notation in our key names. That is, accessing the value stored at the key value ‘foo’ in the nested object ‘data’ is done writing “<em>data-foo</em>” rather than “<em>data.foo</em>” or “<em>data[‘foo’]</em>” as one would expect.</p><p>This is documented–but it was not our first thought when initially debugging.</p><h4>Integrated Logical Operations</h4><p>Another shortcoming of Amazon Connect is the lack of supported mathematical operations. The team I’m on was in need of checking an external cache several times before terminating a call. The cache was populated with data based on a customer action, and as such, we wanted to act as close to real time as possible while we waited for them to take the action. To do this, we wanted to loop for a minute, check the cache, and terminate if/when the customer took this action.</p><p>We thought this sounded like a simple enough task, but Connect does not support looping based on time with a condition. We could put the customer on hold for a minute and <em>then </em>check the cache (keeping the customer on a one minute hold regardless of whether the action was taken or not), and we could loop over some condition (the counter logic had to be put in AWS Lambda) and take an action based on the result; but, we could not mix the two.</p><p>Small things like this make us think more simply about what we can quickly and easily achieve in Amazon Connect; which is unfortunate since the rest of Amazon Web Services tend to allow us to think about doing more complex things than having on-prem resources would allow us to.</p><h4>CI/CD</h4><p>By far the biggest frustration we’ve had with Amazon Connect so far is that, at this time there is no API for creating Contact Flows, nor is there an API to import JSON representation of Connect Flows. This makes integrating your IVR configuration into continuous integration (CI) platforms near impossible. In addition to this, the Contact Flow configuration language is complicated and includes data not needed by whatever CI tool you use, such as the <em>x</em> and <em>y</em> coordinate of the contact block the configuration represents.</p><p>That’s not to say <a href="http://www.solutonashville.com/">Soluto Nashville</a> isn’t crazy about Amazon Connect. The direct integration with Lex and AWS Lambda liberate us in a lot of ways. But there are still some kinks to be worked out and a few features we’re eager to have added.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e26eefc2ecae" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/adventures-in-amazon-connect-e26eefc2ecae">Adventures in Amazon Connect</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Your First Responsibility in Any Job]]></title>
            <link>https://medium.com/soluto-nashville/your-first-responsibility-in-any-job-df5be5675a81?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/df5be5675a81</guid>
            <category><![CDATA[empathy]]></category>
            <category><![CDATA[culture]]></category>
            <category><![CDATA[self-improvement]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[leadership]]></category>
            <dc:creator><![CDATA[Alex J. Hughes]]></dc:creator>
            <pubDate>Mon, 11 Jun 2018 12:50:06 GMT</pubDate>
            <atom:updated>2018-06-11T12:49:24.406Z</atom:updated>
            <content:encoded><![CDATA[<h4>Before the customer, experience, or achievements</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mmZY35mg-OqgyoPMQJYXLg.jpeg" /></figure><p>Many smart creatives have lofty ambitions — a desire to create something meaningful, make a difference, improve the world. But it’s easy to get caught up in these aspirations and overlook your most important responsibility.</p><p>Each of us has the capacity to directly impact (and improve) a handful of people’s lives on a daily basis through our work. This is our obligation to each other — no matter how high our position or perceived impact.</p><p><strong>When you come into work each morning, your first job should be to improve the quality of life for your immediate team. </strong>It doesn’t matter if you’re an engineer, analyst, designer, manager, or intern. Everything starts with the people around you. Take your ego out of it. Only then will you be able you branch out and improve, as a group and individuals.</p><p>Building the morale of your team is what precedes creating anything of lasting value.<strong> </strong>If you don’t get it right at this immediate level, it’s impossible to sustain at higher levels of performance with multiple moving pieces.</p><p>This can be better understood as a five-tier model, similar to a rather famous hierarchy of needs.</p><h4><strong>Levels:</strong></h4><ol><li>Improve the lives of those on your immediate team</li><li>Elevate the quality of individual and group contributions</li><li>Establish and grow the culture</li><li>Advance the overall mission and purpose</li><li>Contribute something meaningful to the world and improve people’s lives</li></ol><p>The people around you come first. Before the customer. Before the experience. Before the achievements.</p><p><strong>Improving the lives of those around you doesn’t mean making things easier, and it doesn’t mean people pleasing.</strong> What it does mean is engaging, challenging, collaborating, and empathizing. And it all must be authentic —everyone’s different, it takes time to build trust and develop your own cadence and rapport.</p><p>Environments where people care and know how to push each other, produce better outcomes. This is where the seeds of cultured are sown.</p><p>While it’s an individual attitude at its core, you can also structure teams in a way that facilitate this type of growth and interaction. Small empowered teams — what we refer to as <a href="https://medium.com/soluto-nashville/a-better-way-to-build-products-the-journey-team-model-f1843026911">journey teams</a> — encourage people to check their egos and focus on coming together. It’s the same mentality in startups — lean, resourceful teams who care about each other, their values, and their mission.</p><p><strong>Those who are only in it for themselves will struggle to survive in this type of an environment.</strong></p><p>There’s less room to hide behind personal brand — or whatever garbage they disguise it as. While this might work in a more rigid, corporate hierarchy, true motivations become glaringly obvious on self-sufficient teams. Pretending to care about the people around you because you’re supposed to, is not the same as actually being invested. You can’t fake that. At least not for long without breeding resentment and disengagement.</p><p>Authenticity, purpose, and challenge are each important if you want to keep smart creatives engaged and contributing their best work. This is one of the most significant obstacles that companies face in today’s business world. That’s why so many people are on the two-year plan, bouncing from one opportunity to the next. It’s difficult to sustain a high level of engagement for years on end.</p><p>The best way to combat this is by building a community of people who not only challenge, but care deeply about each other. It’s a true competitive advantage that’s not easily replicated. It’s hard work, that’s why it’s so rare. But few things have a more powerful, direct contribution to your overall wellbeing than this type of work environment.</p><p><strong>If you want to make a difference, start by making a difference in the people’s lives immediately surrounding you, then build from there. </strong>This remains true regardless of what aspirations you hold.</p><p>Show compassion and interest towards the people you work with. Discover meaning in your work, together. Enjoy your time together, struggle together, and strive to improve each other’s lives.</p><p>If you want to achieve what you’ve set out to, you’re going to need people who care about and challenge each other. That’s what it takes to bring an idea to life and contribute something meaningful to the world. When you make this your first responsibility, everyone will come out better for it.</p><h4>Looking for an edge? <a href="https://www.alexjhughes.com/subscribe/">Join my newsletter</a> to receive my “Top 4 Books for Better Mental Models” as a welcome gift, just check your email.</h4><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=df5be5675a81" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/your-first-responsibility-in-any-job-df5be5675a81">Your First Responsibility in Any Job</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[10 Journey Team Best Practices]]></title>
            <link>https://medium.com/soluto-nashville/10-journey-team-best-practices-95b73cad75b?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/95b73cad75b</guid>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[product-management]]></category>
            <dc:creator><![CDATA[Sead Dzelil]]></dc:creator>
            <pubDate>Wed, 30 May 2018 15:08:20 GMT</pubDate>
            <atom:updated>2018-05-30T15:08:19.842Z</atom:updated>
            <content:encoded><![CDATA[<p>Great product teams need the right working model. We’ve found that small, empowered teams have the ability to make the biggest difference — we call them <a href="https://medium.com/soluto-nashville/a-better-way-to-build-products-the-journey-team-model-f1843026911">Journey Teams</a>. At <a href="http://www.solutonashville.com/">Soluto Nashville</a>, we have over a dozen of these teams, all operating with a slightly different approach. But they all share some commonalities. We consider these to be best practices for working in this model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/598/1*gDOGI9SOdN6-s9IGQq2j1g.png" /></figure><h4><strong>1. A clear team goal</strong></h4><p>A clear goal gives the team a desired outcome to work toward, and it provides focus. The desired outcome rallies the team and helps with prioritization every week. Focus ensures that the team’s energy is channeled properly to achieve the desired outcome and avoid distractions.</p><p>Think about holding out a magnifying glass on a bright summer day. You want to channel that energy to burn straight through the objective in sight.</p><p>Alignment around goals is so important that our teams are named after them — Employee Onboarding, Partner Enablement, Rich Session, Relevant Content, etc. Occasionally we’ll get more specific and use longer versions of team names, like “Finding the best employees” and “Launching new partners faster.”</p><h4><strong>2. KPIs aligned with the team goal</strong></h4><p>Data is better than opinion. Key Performance Indicators (KPIs) are metrics that allow teams to baseline and measure progress towards their goal. They ultimately tell the story of whether a team is successful or not. For example, a KPI for our Rich Session team may be the percentage of support sessions that take place in a rich channel (more than just telephony).</p><h4><strong>3. Autonomy to achieve the team goal</strong></h4><p>A team should be able to achieve their goal without dependencies on other teams or individuals. All members are fully allocated to the team and together they have the necessary skills to affect their KPIs. This helps to inspire and empower the team, since they are in control of their own destiny. The feeling is similar to that of a startup.</p><p>Dependencies introduce costly hand-offs that slow teams down and should be avoided. When there are dependencies, such as when a team needs a modification to a software component that’s owned by a different team, we encourage teams to enable others to modify their components with some review.</p><h4><strong>4. Weekly planning meeting resulting in specific goals</strong></h4><p>To ensure the team has a clear path for the week and is empowered to make measurable progress, it’s important to have a brief planning session at the start of every week. We call these “calibration meetings” because ideation and planning are ongoing activities. The purpose of this meeting is to prioritize work and commit to weekly goals.</p><p>Features are broken up into cards that can be delivered in less than 3-4 days and added to the Kanban board. To ensure that each card delivers product value, it is best to <a href="https://agileforall.com/vertical-slices-and-scale/">vertically slice</a> features. A Work-In-Progress (WIP) limit ensures that teams are focused. A good rule of thumb is that a team with 3 engineers should not be developing more than one or two features at the same time. That’s because one fully done feature, that’s deployed to production, is a lot more valuable than many half done features that are in flight.</p><p>Each Monday, teams should ask themselves, “What are we going to get done this week that we’ll feel good about?” The outcome of a weekly calibration meeting is: one or more specific weekly goals reflected on the Kanban board as cards. The team then works to move the cards to “Done” by the end of the week, holding each other accountable.</p><p>Weekly goals are a great way for the team to keep their intensity level high in order to make amazing progress.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SyGLcOO8Weo8pqSuQgUr0A.png" /></figure><h4><strong>5. Daily standup meeting</strong></h4><p>Every morning, teams should sync up in person (5–15 minutes) to review the Kanban board and ensure everyone’s on the same page.</p><p>A common format is:</p><ul><li>What was done on the task yesterday?</li><li>What will be done today?</li><li>Are there any blockers?</li></ul><p>Although there is nothing wrong with every team member giving an update individually, it is more important to update progress on the team’s most important tasks — which should all be reflected on the Kanban board as cards. Visualizing cards, workflow, and progress on a Kanban board is a proven way to improve productivity.</p><h4><strong>6. Bi-weekly retrospective meeting focused on continuous improvement</strong></h4><p>Every two weeks, the team should meet to discuss how they can get better in the interest of continuous improvement. It’s important for this to be a dedicated, recurring meeting with a singular focus. This encourages team members to come into the discussion with the right mindset and be open and direct about how to improve as a team.</p><p>Most retrospective formats have four parts:</p><ul><li>What went well in the past two weeks?</li><li>What didn’t go well in the past two weeks?</li><li>What are the action items to help us get better?</li><li>Review the previous retrospective’s action items to make sure they were addressed</li></ul><p>Without this type of meeting, improvement is difficult to come by. And if you’re not making a conscious effort to improve, you’re getting worse.</p><h4><strong>7. Write a short pre-spec to get to a shared understanding</strong></h4><p>Before starting work on any non-trivial feature, the team should get together to discuss the objective of the feature, how it will work, and how to measure success. It’s important to write this down. It can be in Jira, Confluence, Google Docs, etc. The tool is not as important as making sure the document is easily shareable. The act of discussing and writing it down forces the team to be precise and have the clarity of thought that’s necessary to build software. The goal is to get to a shared understanding of what they want to achieve. A side benefit is that other teams and individuals can easily learn what’s being built by referencing the one-pager.</p><p>When a feature is conceived, the team first comes up with a hypothesis. Hypothesize and test is the essence of the <a href="https://en.m.wikipedia.org/wiki/Scientific_method">scientific method</a>. Its application is one of the central tenets of the <a href="http://theleanstartup.com/principles">lean startup</a> methodology. A hypothesis for our Session Quality team could be something like “Moving the 5 star survey from a standalone web page into our mobile app will increase take rate.” In this example, the team would enable this feature for a cohort and see if the take rate KPI increased compared to the control group.</p><p>A common format for a pre-spec is less than one page and includes these sections:</p><ul><li>Hypothesis</li><li>High-level overview (can be in User Story format)</li><li>Description of how the feature will work (can be in Acceptance Criteria format)</li><li>Description of how success will be measured (what analytics events need to be sent and what data will be reviewed)</li></ul><p>Without writing it down, it’s easy for people to walk away with different or ambiguous understandings of what will be built. The pre-spec can be a living document and it can include links to the UX design and technical design.</p><h4><strong>8. Work collaboratively</strong></h4><p>UX designers work very closely with product managers to design how each feature will work. They spend time on the same whiteboard or computer creating wireframes or high-fidelity prototypes. They frequently run their designs by the engineers to get feedback on design and implementation complexity.</p><p>Engineers regularly solicit feedback from teammates as they develop. They discuss technical challenges with their fellow engineers and pair on code. They demonstrate functionality early and often to get feedback from UX designers and product managers.</p><p>All this is enabled by the product manager, UX designer, and engineers sitting closely together. Team members are committed to providing psychological safety and roughly equal speaking time for all.</p><h4><strong>9. Create a light technical design before writing code</strong></h4><p>For any non-trivial feature, the engineers think and talk through the technical design before writing code. The technical design can consist of one or more diagrams like class diagrams, sequence diagrams, flowcharts, etc. These can be drawn on a whiteboard, Confluence, or any other tool. Don’t worry too much about the format or tool. What matters is talking through the technical design before writing a significant amount of code.</p><p>We find that doing this has many benefits. First, a better technical solution is produced because multiple engineers contribute ideas. Second, it’s a learning opportunity for less experienced engineers. And lastly, it ensures that there are no lengthy design discussions during code review that cause costly refactoring and frustrations.</p><h4><strong>10. Collect and analyze data and user feedback for every feature</strong></h4><p>Teams collect and analyze data and user feedback for every feature. Analytics are built in by default. This is usually in the form of events going to an analytics platform, like Mixpanel.</p><p>The team analyzes how much the feature is being used as well as whether it is affecting their KPIs. Product managers and UX designers collect feedback from users through interviews and surveys. User feedback (qualitative) complements the analytics data (quantitative). Data and user feedback tell the team whether a feature is successful or not, and that drives what the team works on next.</p><p>Sometimes the data and feedback are not positive. And that’s okay. Teams are encouraged to experiment and should not be afraid to fail. Leadership encourages taking risks and failing fast. What’s important is that the team learns something every time and moves the KPIs in the right direction in the long run.</p><h4><strong>Summary</strong></h4><p>The practices mentioned above have been developed over years of trial and error by our Soluto Nashville teams. Like all organizations, ours is unique in team structure, culture, and product goals. So we recognize these practices are not a one-size-fits-all solution. But we encourage all teams to take the plunge and strive toward working in the Journey Team model.</p><p><em>If you’re interested in joining our team, feel free to check out the job openings at </em><a href="http://www.solutonashville.com/"><em>Soluto Nashville</em></a><em> and send me a note!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=95b73cad75b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/10-journey-team-best-practices-95b73cad75b">10 Journey Team Best Practices</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Better Way to Build Products: The Journey Team Model]]></title>
            <link>https://medium.com/soluto-nashville/a-better-way-to-build-products-the-journey-team-model-f1843026911?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/f1843026911</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[agile]]></category>
            <category><![CDATA[lean-startup]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[product-management]]></category>
            <dc:creator><![CDATA[Sead Dzelil]]></dc:creator>
            <pubDate>Fri, 06 Apr 2018 17:40:24 GMT</pubDate>
            <atom:updated>2018-04-06T17:40:23.314Z</atom:updated>
            <content:encoded><![CDATA[<p>To consistently build exceptional products, you need the right working model and process. At Soluto, we’ve developed what we call “Journey Teams” — inspired by both the Lean Startup methodology and Spotify engineering culture videos. The name comes from the concept of mapping a user’s journey with a product or service. Our Soluto teams are designed around unique points of the user’s journey. Journey Teams have their core tenets, but let’s look back at a few different models to see how we landed here.</p><h3><strong>Waterfall</strong></h3><p>When I started my career as a software engineer, my company operated in a traditional Waterfall model. A Business Analyst would spend months meeting with “the business,” writing and revising a Functional Specification document. This document would often be hundreds of pages long, describing in detail how the software should work. The document would be handed to an engineering manager who would then assign one or more engineers to work on it. As a junior engineer, I enjoyed it because I could spend all my time on what I preferred to focus on — writing code.</p><p>But, there are a lot of problems with Waterfall software development. It can take months or years to go from ideation to shipping. Furthermore, the Functional Specification never reflected what the users actually needed. The length of the feedback loop was too long. The team would get the first real user feedback only once the product was fully implemented and shipped to production. And even if the Business Analyst was a genius, a lot could change in the business environment between the time the document was written and the time the engineering team actually shipped the product. The bottom line is that, in the Waterfall model, the product being shipped rarely reflected what the users needed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_mH8pFiSsPp4vrAVStV4bQ.png" /></figure><h3><strong>Scrum</strong></h3><p>Companies slowly evolved and became “agile.” Most companies adopted the <a href="https://en.wikipedia.org/wiki/Scrum_(software_development)">Scrum</a> methodology when they first moved from Waterfall to Agile software development. Scrum was better for a handful of reasons. Teams focused on developing Minimum Viable Products (MVPs), which got them to production faster. Iterations were shipped more often. Faster implementation and iteration helped ship more of what users really needed because it shortened the feedback loop.</p><p>But, Scrum has problems as well. Even though it’s lighter weight than Waterfall, it still comes with quite a bit of process baggage. It requires a Scrum Master to facilitate the Scrum process and sprint ceremonies. You have to plan, prioritize, and estimate (“story point”) weeks worth of work at a time. One common issue teams faced was priority changes or “something urgent” coming up mid-sprint. Sometimes, we would put it in the next sprint and miss an opportunity. Other times, we would take it on and bump other stories to a future sprint.</p><p>Another issue we faced in Scrum is the emphasis placed on accurate estimates — something humans are notoriously bad at. We would often push ourselves hard to compensate for underestimating stories. If you’re bad at estimating, as most people are, or you work in an environment where priorities change often and you have to react to “urgent tasks,” this emphasis on sprint commitments can quickly burn a team out.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f9QXA1QMaA4DSxrLeg6Ohw.png" /></figure><h3><strong>Kanban</strong></h3><p>Moving from Scrum to <a href="https://en.wikipedia.org/wiki/Kanban">Kanban</a> fixed many of these problems. Kanban is lean, more lightweight than Scrum, and a lot less prescriptive. There are no special roles, sprints, high-stakes estimates, or planning out weeks worth of work at a time. You break stories and tasks down into things that can be completed in 3–4 days. You deploy them to production as soon as they are done.</p><p>With Kanban, there are still daily standups, retrospectives, and weekly planning meetings. But teams can react to priority changes at any time, without bureaucracy. A Work In Progress (WIP) limit ensures that you have focus. The goal is to minimize the amount of in-flight work that is not complete. That’s because having one feature 100% done and in production is much better than having two features halfway done.</p><p>One secondary benefit of WIP limits is pairing engineers on tasks. This ensures tasks get completed faster and engineers are able to learn from each other, improving quality as a result of the constant peer review. Additionally, the knowledge is better spread out, so that if one engineer goes on vacation, there are others who are deeply familiar with the code.</p><p>But using Kanban does not guarantee that you will build exceptional products. Teams can still have constant priority battles. Teams can still be blocked by dependencies. Teams can still be structured wrong. They can be large and have strict roles and hierarchy. And, teams may still not measure themselves objectively.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uWSPsQ9NcCArhNci_JaXVw.png" /></figure><h3><strong>Journey Teams</strong></h3><p>Here’s where our Journey Team model takes off. We start with Kanban and add a few key tenets<strong>.</strong></p><p><strong>Journey Teams are…</strong></p><p><strong>…focused on desired outcomes</strong></p><p><strong>…autonomous</strong></p><p><strong>…small, flat, and cross functional</strong></p><p><strong>…feedback and data driven.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1020/1*DfCGg7Vr-tnafx5eTLVGaA.png" /></figure><p><strong>Journey Teams are focused on <em>desired outcomes</em>.</strong> <br>It’s important not to create teams around layers in a technology stack like “Database Team,” “Services Team,” “Mobile Team,” or “Web Team.” Journey Teams are not even created around specific products like “Knowledge Base Team” or “CRM Team.” They are created around <em>desired outcomes</em>.</p><p>Teams are measured by Key Performance Indicators (KPIs) around those outcomes. For example, if you’re building a Technology Support service, you may have a Journey Team called “Employee Onboarding.” Their mission may be to find, vet, and hire the best possible experts for helping customers with technology support questions. A KPI for this team could be something like “number of experts onboarded this month” or “cost per onboarded expert.” A name, short mission statement, and a KPI — all aligned with a <em>desired outcome </em>for the company<em> — </em>gives the team an important sense of focus and the ability to measure their progress. This focus on KPIs keeps the team from having constant “priority battles” that are common in Scrum or even pure Kanban.</p><p><strong>Journey Teams are autonomous</strong>. <br>In the ideal environment, a Journey Team should never be dependent on any team or individual outside of the Journey Team. We consider dependencies to be evil. In the example above, the “Employee Onboarding” team should be able achieve their mission and affect their KPI without dependencies. This takes away excuses. It also gives the team a sense of ownership, empowerment, and inspires a start-up spirit.</p><p><strong>Journey Teams are small, flat, and cross functional.</strong> <br>They are usually composed of a product manager, a UX designer, a test engineer, and two to four software engineers. Although one of the engineers is a “tech lead,” there is no reporting hierarchy on the team. An engineer may help with UX. A UX designer may help out with product management tasks. Everyone contributes product ideas. Every engineer works on the full stack — services, web, mobile, etc.</p><p>Keeping the team small creates a strong sense of comradery and improves collaboration by keeping the number of communication lines low. Not having a reporting hierarchy and allowing people to play different roles, keeps everyone engaged and takes advantage of everyone’s full potential.</p><p><strong>Journey Teams are data and feedback driven.</strong> <br>Rather than making a big assumption, building a feature, then releasing to production without any further feedback, our teams take a different approach. Initially, we build the feature as an experiment and deploy it to a small cohort of users. The team has the ability and freedom to deploy often. The technology to enable a feature for a small cohort of users is critical in this model (you can use <a href="https://github.com/Soluto/tweek">Tweek</a>, for example). It’s also important to have the right technologies in place to capture and broadly share data from the experiment (we use tools like <a href="https://mixpanel.com/">MixPanel</a> and <a href="https://www.geckoboard.com/">Geckoboard</a>).</p><p>Once the experimental feature is deployed to a small cohort, the team looks at the data and collects user feedback. Data for the cohort that has the feature is compared to the cohort that does not have the feature (this is known as <a href="https://en.wikipedia.org/wiki/A/B_testing">A/B testing</a>). If the experimental feature proves to be beneficial — for example, it increases the number of qualified experts that are brought on in the “Employee Onboarding” example above — the feature is scaled to all users. The data (quantitative feedback) is augmented by user feedback (qualitative feedback) when appropriate.</p><p>If the data or feedback shows that the experimental feature is not beneficial, the team takes those learnings and devises a new experiment. In either case, data and feedback drive what the team works on at every step.</p><blockquote>Journey Teams are an effective and rewarding way to build products. Focusing on desired outcomes ensures that we build the right things, rather than simply putting out well designed and engineered features. Establishing autonomy enables us to move extremely fast, since we are never blocked and waiting on others. In terms of structure, our small, flat, and cross-functional teams unleash everyone’s talents, regardless of role or seniority. Finally, remaining focused on data and user feedback enables us to measure the impact we’re making towards real outcomes, rather than vanity metrics like story points.</blockquote><p>In this article, I wanted to share my personal experiences with various Product Development processes and give an overview of Journey Teams. We’ll write more on this topic, so check back often. And if you’re interested in joining our team, feel free to check out the job openings at <a href="http://www.solutonashville.com/">Soluto Nashville</a> and send me a note!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f1843026911" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/a-better-way-to-build-products-the-journey-team-model-f1843026911">A Better Way to Build Products: The Journey Team Model</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Hackathon in 5 Easy Steps]]></title>
            <link>https://medium.com/soluto-nashville/how-to-hackathon-in-5-easy-steps-a00ae17b19fe?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/a00ae17b19fe</guid>
            <category><![CDATA[product]]></category>
            <category><![CDATA[presentations]]></category>
            <category><![CDATA[hackathons]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Brandon Evans]]></dc:creator>
            <pubDate>Wed, 31 Jan 2018 23:58:54 GMT</pubDate>
            <atom:updated>2018-02-02T21:44:38.221Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LJj4hmOES-c0DYj4Kwg89A.jpeg" /></figure><p>Why aren’t more people talking about Hackathons? They’re a blast and frequently supply free food and fidget spinners. But most importantly, they’re a great way for software developers to improve their skill set in a short amount of time, while offering non-technical professionals an opportunity to execute a vision and bring an idea to life.</p><p>If you’re interested in entering one, colleges and tech-related organizations hold them all the time. I am proud to work for a company (<a href="https://www.asurion.com/">Asurion</a>) that sponsors an annual hackathon, which produces dozens of innovative ideas and impressive implementations. During this year’s event, other than managing to surround myself with great teammates, I followed these five steps to optimize my hackathon experience.</p><h4><strong>1. Pick something topical</strong></h4><p>Many interesting projects come out of hackathons, but after you’ve been to a few, you’ll start to see some repeats. To maximize novelty, try picking a relatively new technology or theme. Even if you don’t win, you’ll learn more and expand the constraints of your comfort zone.</p><p>For example, due to the massive increase in home assistant ownership (129% year over year), our team decided to utilize the Amazon Echo for our hack. Our service, <a href="https://www.asurion.com/soluto-service/">Soluto</a>, provides instant premium support for technology issues. We thought that the Echo could be a convenient entry-point to our service.</p><p>Your hackathon idea doesn’t always need to change the world. It can be something simple and fun that’s inspired by an engaging new show, movie or game. I participated in my first hackathon a few years ago when <a href="https://gabrielecirulli.github.io/2048/">2048</a> originally came out. Because one of our sponsors was <a href="https://sendgrid.com/">SendGrid</a>, I decided to hack together an <a href="https://github.com/BrandonE/2048-SendGrid">email-powered 2048 game</a>. It was well received, due to its relevance at that time.</p><h4><strong>2. Define an MVP</strong></h4><p>Most hackathons last between 24 and 72 hours. Although this might seem like it’s a lot of time to work with, it’s not, even if you bring a sleeping bag. As such, you need to define a <em>minimally viable product </em>(MVP) that’s feasible for your team to create, while leaving you time to spare.</p><p>You can accomplish this by limiting your hack to a few core features. If your hack is too broad, each feature will likely appear unpolished. If you have ideas for how to expand your hack in the future, include them in your presentation as talking points. The audience and judges won’t forgive you, however, if you have a great sales pitch but nothing tangible to show for it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UrvV7Gu9NzKzd1hOVZZEsg.jpeg" /><figcaption>Award Ceremony at the 2017 Asurion Hackathon (Nashville). From left to right: Barry Vandevier (Judge and President of Operations), Alex Hughes, Lucas Rudd, Jonathan Hughes, Daniel Cottone, and Brandon Evans</figcaption></figure><h4><strong>3. Test third-party integrations early</strong></h4><p>Many hacks utilize <em>application programming interfaces</em> (APIs) to integrate their application with other web-based services. You can have your users log in through their Google account, send out tweets chronicling their in-app activity, and much more. Using APIs expands your target audience, simplifies development work, and enriches your user experience.</p><p>Unfortunately, APIs, by design, have their limitations. These third-parties worked very hard for their databases and features, and they’re not going to let you use them unabated. Some APIs require payment, most limit how many calls you can make within a given amount of time, and all restrict access to their data in some way. To avoid any misconceptions, you should test your integration use-case early, perhaps before creating any other functionality.</p><p>I learned this the hard way. At a previous hackathon, my team set out to create a Facebook application that identified which friends you haven’t interacted with recently, and gave you the option to reconnect with them. We built the entire application during the first half of the hackathon before starting the API integration. There was only one problem: Facebook prevents you from getting information about your friends <strong>unless they also have the app</strong>. As the app would be useless until a significant part of the population installed it, we had to completely rework our idea with very limited time.</p><p>At the Asurion Hackathon, we benefited from being able to use internal APIs that we’ve worked with in the past. Even still, we worked on the integrations first, just in case anything came up along the way. This allowed us to focus most of our energy on creating and refining the user experience.</p><h4><strong>4. If it ain’t broke, don’t fix it</strong></h4><p>If you’ve implemented your MVP with time to spare, you might be tempted to change it in some way. Your team <strong>should not </strong>take this decision lightly. A hack is not a ready-to-market product. Last minute code refactoring has no place at a hackathon. If your hack could use some additional user-facing improvements or features, you need to evaluate what the risk vs. reward of these changes are, and give yourself time to recover if something goes wrong. At minimum, I would refrain from making any modifications to the hack within an hour of your final presentation. At some point, you have to stop breaking things!</p><p>This doesn’t mean that you shouldn’t create a list of possible changes to tackle at another time. As previously mentioned, a hack, if done correctly, is just an MVP, not a finished product. But that shouldn’t stop you from thinking about future iterations on the concept. Hopefully, your hack is something you believe in, so feel free to pick the project back up after the competition ends. Just don’t risk breaking anything right before your presentation. Speaking of which…</p><h4><strong>5. Present like your hack depends on it (it does)</strong></h4><p>Some hackathons have sequential demonstrations, while others have showcases where judges check out the hacks at their leisure. Either way, presentation matters as much, if not more, than the hack itself. If you have an amazing project but can’t convey its awesomeness, what’s the point? Make sure to dedicate a significant amount of your time to preparing and practicing your presentation.</p><p>This is where having non-developers on your team can be tremendously helpful. After defining the MVP, these members of the team can plan how to best market it in parallel with development — so long as both groups communicate with each other about any major changes. Developers can help focus on the “what,” while the others help refine the “why.”</p><p>Before designing your pitch, you must identify your audience. If your hackathon invites the public to judge, you’ll want to capture their attention and keep it light on the nitty-gritty. If you’re presenting to business stakeholders, incorporate key financial projections and examples of value-adds for the organization. Lastly, if your fellow hackers are rating your project, go over the tech stack and show-off the intricacies of your architecture.</p><p>The most memorable presentations are usually the most interactive ones. It’s one thing to witness a program being used; it’s another to experience it for yourself. If you can find a way to allow the audience to demo your product, go for it (as long as you’re cognizant of your potential edge-cases).</p><p>If you follow these steps, you should leave the hackathon with an interesting, unique, and well-executed deliverable. This is not to say that you’re guaranteed to win, but that’s far less important than the skills and experience you gain from participating in these events.</p><p><em>If you’re interested in joining our team, feel free to check out the job openings at </em><a href="http://www.solutonashville.com/"><em>Soluto Nashville</em></a><em> and send me a note!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a00ae17b19fe" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/how-to-hackathon-in-5-easy-steps-a00ae17b19fe">How to Hackathon in 5 Easy Steps</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[3 Hats of a Data Scientist]]></title>
            <link>https://medium.com/soluto-nashville/3-hats-of-a-data-scientist-6cff36765b04?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/6cff36765b04</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[data-warehouse]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-wrangling]]></category>
            <category><![CDATA[data-analysis]]></category>
            <dc:creator><![CDATA[Sharon Chou]]></dc:creator>
            <pubDate>Mon, 29 Jan 2018 17:07:10 GMT</pubDate>
            <atom:updated>2018-01-29T17:07:10.178Z</atom:updated>
            <content:encoded><![CDATA[<h4>Adventures in swapping metaphorical headgear</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_vpCQY-ryHUdbcd_lofqbg.png" /></figure><p>Data Science is a strange creature, the hybrid chimeric offspring of machine learning and statistics. Its sightings are numerous yet confounding, because it’s often not well-defined and takes different forms depending on the data and people involved.</p><p>In the context of business problems, the “science” in data science really boils down to just “finding out more,” in the spirit of <em>Scientia</em> — “to know.” It aligns well with my personal driving principle of making discoveries. I want to uncover previously unknown patterns in how processes work, whether physical, biological, or sociological.</p><p>During my time working as a data scientist, I have rotated among three different roles at various stages of data-centric projects, characterized as the following:</p><h3>The Forager / Hunter</h3><p>Every data science problem starts with finding the necessary data. In an ideal world, it lives in data warehouses or databases like neatly labeled grocery store aisles and shelves. (Thank goodness for <a href="https://en.wikipedia.org/wiki/Data_architect">data architects</a> and <a href="https://cognitiveclass.ai/blog/data-scientist-vs-data-engineer/">engineers</a>!) In the non-ideal case, it grows in hard-to-reach mountain peaks or hangs out at the bottom of a murky <a href="https://en.wikipedia.org/wiki/Data_lake">data lake</a>. Most of the time it’s somewhere in between.</p><p>On good days, you can write brief <a href="https://en.wikipedia.org/wiki/SQL">SQL</a> <a href="https://www.w3schools.com/sql/sql_select.asp">SELECT</a> queries to fetch the data from a database. On other days, you might need to summon <a href="https://techterms.com/definition/api">APIs</a> and contend with access tokens and certificates. Sometimes just exposing the data can help tremendously — if no one has had access to it before. Different teams can have different uses for the same dataset, and simply extracting it to a central location is a great enabler, be it an <a href="https://en.wikipedia.org/wiki/Amazon_Web_Services">AWS</a> database or Google Sheet.</p><h3>The Chef</h3><p>Like food preparation, there’s often a lot of data prep involved before applying any statistical or machine learning algorithm. To ensure the best result possible, the raw data needs to be cleaned and trimmed to its most relevant essence.</p><p>In any given use case, there are far more ways for the data to have wrong formats than right ones. <a href="https://www.goodreads.com/quotes/7142-all-happy-families-are-alike-each-unhappy-family-is-unhappy">Good datasets are mostly alike</a>; <a href="https://en.wikipedia.org/wiki/Anna_Karenina_principle">bad datasets are problematic in their own ways</a>, e.g. misspelled or missing names, emails, commas in CSV files, inconsistent timestamps due to time zones or Daylight Savings time.</p><p>For data tables, the next step is to slice and dice, or merge and combine, using either SQL, Python, or R. For more intricate data structures like nested <a href="https://www.json.org/">JSON</a> files, they need to be <em>peeled like onions until they burn the eyes</em>.</p><p>Most commonly used machine learning or statistical algorithms are well-developed now. They range from the simple-to-use-and-explain like <a href="https://en.wikipedia.org/wiki/Simple_linear_regression">regressions</a> (think pots and pans), to the simple-to-use-but-difficult-to-explain like <a href="https://en.wikipedia.org/wiki/Artificial_neural_network">neural nets</a> and <a href="https://en.wikipedia.org/wiki/Random_forest">random forests</a> (think microwaves).</p><p>While these algorithms are often implemented in <a href="http://scikit-learn.org/stable/">packaged</a> <a href="https://www.computerworld.com/article/2921176/business-intelligence/great-r-packages-for-data-import-wrangling-visualization.html">libraries</a>, the default settings don’t always work well. <strong>You cannot simply plug-and-play</strong> because the algorithms have many input parameters that need to be adjusted for different problems. Frying a fish requires different condiments than sautéeing Brussels sprouts, in addition to different cooking times and heat settings.</p><p>Once you’re happy with the analysis results (plated dish), the next step is presentation.</p><h3>The Waitstaff</h3><p>Neighborhood diner fare, like sandwiches or meatloaf can be brought out as is, because most people know what they are. The waiter does not (usually) need to explain where the ingredients came from. They are the equivalent of an Excel table with a title and headers, or bar charts with axis labels. The information should be easy to digest, the trends obvious to see, and actionable items readily apparent.</p><p>The more complex visualizations such as <a href="https://seaborn.pydata.org/examples/structured_heatmap.html">cluster maps</a> or multiple histograms with logarithmic scales need more finesse to make them understandable–like when a maitre d’ describes a dish as the perfect pairing between alpine moss foam and deep sea bass. Complex plots can show more nuanced information, but the key points still need to be highlighted so the audience is not overwhelmed by sensory overload.</p><p>The goals of data presentation can be a combination of revealing insightful discoveries or calls to action. The stakeholders should see accurate data representations that they’re able to learn from and clearly interpret, in order to make the best decisions going forward.</p><p><em>If you’re interested in joining our team, feel free to check out the job openings at </em><a href="http://www.solutonashville.com/"><em>Soluto Nashville</em></a><em> and send me a note!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6cff36765b04" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/3-hats-of-a-data-scientist-6cff36765b04">3 Hats of a Data Scientist</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Became a Better Writer]]></title>
            <link>https://medium.com/soluto-nashville/how-i-became-a-better-writer-da4261bf091e?source=rss----4da90db368ce---4</link>
            <guid isPermaLink="false">https://medium.com/p/da4261bf091e</guid>
            <category><![CDATA[writing]]></category>
            <category><![CDATA[writers-on-writing]]></category>
            <category><![CDATA[writers-block]]></category>
            <category><![CDATA[writing-tips]]></category>
            <dc:creator><![CDATA[Taryn R. Wolf]]></dc:creator>
            <pubDate>Thu, 25 Jan 2018 20:16:10 GMT</pubDate>
            <atom:updated>2018-01-25T20:16:10.495Z</atom:updated>
            <content:encoded><![CDATA[<h4>10 changes I’ve made to improve my writing</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*B_7lJQZsJbrSOlrs_yDJjg.jpeg" /></figure><p>Writing is a skill we use everyday, and it’s also one of the hardest to perfect. As Hemingway once said, “It’s none of their business that you have to learn to write. Let them think you were born that way.”<br>I know for myself, as a professional writer, I’ve battled with confidence in my writing — the constant question, “Am I good enough?” So, I decided to sit down and think about intentional changes I’ve made over the years that improved my work, and therefore my confidence in it. Here are the ten things I came up with.</p><h3>Before you write</h3><blockquote>“<em>All the words I use in my stories can be found in the dictionary — it’s just a matter of arranging them into the right sentences.</em>”</blockquote><blockquote>—<em>Somerset Maugham</em></blockquote><h4>1. Read, read, and read some more</h4><p>I’ve been a reader as long as I can remember. I used to get in trouble in daycare for holding books (I couldn’t even read!), instead of napping. Though reading isn’t a passion for everyone, I can’t stress its importance enough. As George R. R. Martin says, “A mind needs books as a sword needs a whetstone if it’s to keep its edge.” <br>Reading gives a writer a foundation to understand writing rules, like syntax and emphasis. More importantly, it helps you develop empathy and critical thinking skills.<br>Pick up your favorite book and look at the structure of the sentences. What makes you enjoy reading that book? What draws you in? The answers to these questions are your first steps in better developing your own voice.</p><h4>2. Study grammar and learn new words</h4><p>You don’t have to go back to school to learn. You can follow blogs like <a href="http://www.quickanddirtytips.com/grammar-girl">Grammar Girl </a>(she also has a podcast), or get an email with a new <a href="https://www.merriam-webster.com/word-of-the-day">word of the day</a>. You can even be a word nerd, like me, and keep a journal with each new word you learn, its definition, and the sentence you read it in.</p><h4>3. Create an outline for your draft</h4><p>You don’t have to create a formal outline with Roman numerals like you did in school, but some form of a written plan is important. Brainstorm all of your ideas and create a loose structure. When you sit down to write, you won’t get writer’s block because you’ve already finished one of the hardest parts.</p><h3>While you write</h3><blockquote>“This is how you do it: you sit down at the keyboard and you put one word after another until it’s done. It’s that easy and that hard.”</blockquote><blockquote>-Neil Gaiman</blockquote><h4>4. Write the body first</h4><p>I used to get hung up for hours on writing a catchy introduction. The anxiety of taking too long, or feeling like I didn’t know what I was going to write, took a toll on my confidence. So, I started writing all of the meat of my drafts first (this was the stuff I knew), and this helped me gain momentum. I finally stopped getting stuck.</p><h4><strong>5. Don’t delete</strong></h4><p>That darn Delete button. I’ve considered removing it before, but typos! Instead, I won’t allow myself to revise anything in my piece until I’ve completed each section. Surprisingly, this helps me finish. It doesn’t matter what you’re writing, if it’s off-topic, if it’s foolish, or if it’s just bad. Get it out. Keep going. Finish the piece. You can fix all of the things you don’t like later.</p><h4>6. Walk away after your first draft</h4><p>You’ve done it. The draft is written. Now, save it and close out. I know it’s hard, but, you and your article need a break from each other. Try to get a full night’s sleep before you read it again(if you’re at work, maybe a lunch break?). It’ll be easier to read the piece objectively and revise it well after you walk away.</p><h3>After you write</h3><blockquote>“Remember, it is no sign of weakness or defeat that your manuscript ends up in need of major surgery. This is a common occurrence in all writing, and among the best writers.”</blockquote><blockquote>— E. B. White</blockquote><h4>7. Revise and edit</h4><p>Remember when I said not to delete earlier? Here’s where you’ll thank me. It’s so much easier to use the Delete button during editing than to write more content. Think critically here. What can you cut? What can you move?<br>Your first draft should never be your last, and that’s okay.</p><h4><strong>8. Read your work out loud</strong></h4><p>Seriously. Go in a room by yourself, quietly mumble at your desk, whatever. Read out loud, and listen to the words. This is the best way to pinpoint awkward phrasing, and sentences that fall flat — flatlines are dead. :)</p><h4>9. Let someone else read it</h4><p>It’s time to give your content wings; let it fly out there and be read by someone else. Don’t take criticism personally; view it as a way to grow. Reviewers are the buffer between you and your true audience — they’re the guinea pigs for your work. If J.K. Rowling has an editor, you can take a few critiques, too.</p><h4><strong>10. Always remember your audience</strong></h4><p>Read your piece one more time. Did you accomplish your purpose? Did you make it accessible to your intended readers? If not, you may want to go back through and revisit those sections. Watch for your tone and voice — a general rule: if you’re writing something professional, make sure your writing is formal, if you’re writing a blog, then make sure the writing is fun and fresh.</p><h4>You’ve finished your piece. Now what?</h4><p>That’s pretty simple. Write more. If you want to improve your writing, then you have to keep doing it. Write, take a break, and write some more. If you’re not a professional writer, then keep a journal, start a blog (you can keep it private), or work on something creative. Just don’t give up. They say 10,000 hours makes you a master at any skill; this includes writing. I should know, some of my older writing is TERRIBLE, and now I’m employed as a writer. You can do it, too. I promise.</p><p><em>If you’re interested in joining our team, feel free to check out the job openings at </em><a href="http://www.solutonashville.com/"><em>Soluto Nashville</em></a><em> and send me a note!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=da4261bf091e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/soluto-nashville/how-i-became-a-better-writer-da4261bf091e">How I Became a Better Writer</a> was originally published in <a href="https://medium.com/soluto-nashville">Soluto Nashville</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>