<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Olio Apps</title>
    <description>The latest articles on Forem by Olio Apps (@olioapps).</description>
    <link>https://forem.com/olioapps</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F672%2Ff58c0f13-eaf1-4131-a01a-de70fe22bfb0.png</url>
      <title>Forem: Olio Apps</title>
      <link>https://forem.com/olioapps</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/olioapps"/>
    <language>en</language>
    <item>
      <title>A Survival Guide for Your Team's Newest Developer</title>
      <dc:creator>Jacob Irwin-Cline</dc:creator>
      <pubDate>Mon, 26 Oct 2020 18:07:35 +0000</pubDate>
      <link>https://forem.com/olioapps/a-survival-guide-for-your-team-s-newest-developer-4cnp</link>
      <guid>https://forem.com/olioapps/a-survival-guide-for-your-team-s-newest-developer-4cnp</guid>
      <description>&lt;p&gt;After a long-winded search for employment, including copious rejections, maybe you’ve finally landed a sustainable position at a well-grounded company, or maybe you’re still on the hunt. The job market ebbs and flows, but as long as you stay dedicated with your spirits up, you’ll likely be making this transition as well. I started my journey into tech a year ago, and I’ve now been working as a developer at my newest company, Olio Apps, for about 3 months. After a pretty great interview, I felt confident that I would be offered the position. Soon after, I had a start date to look forward to! As anyone would be, I was excited, but I couldn’t help but be nervous as well. I felt like this was a bigger opportunity than my previous positions at small start-ups.&lt;/p&gt;

&lt;p&gt;Throughout these last few months, I’ve learned some things I wish I'd known beforehand, but there have also been things I wish I hadn’t focused on as much. Pulling from my quick onboarding process and other experiences I've had joining teams, I’ve written this guide as a roadmap for new developers, aimed at showing them what to focus on in order to be a successful hire. This "survival guide" should help new developers onboard more effectively, connect with their team in a meaningful way, and focus on the things that matter while joining a new company or team.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YzXBDWnV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zla4j0kwf7r5zp1vw8ok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YzXBDWnV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zla4j0kwf7r5zp1vw8ok.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  First Day
&lt;/h2&gt;

&lt;p&gt;So it’s your first day of work!&lt;/p&gt;

&lt;p&gt;You’ll likely be getting access to the company’s software and email (if not later, depending on the company). You’ll probably be introduced to team members or managers that you’ll be working closely with, then go over your first tasks. Make sure you know what to work on, who to report to, and which tools you’ll need to be an active part of the team. JIRA, Confluence, Slack, and the company Gmail were some of what I was granted access to on my first day.&lt;/p&gt;

&lt;p&gt;I expected there to be delay on some of these things, since there always seems to be… But I was lucky to have a small and lightweight team that got things done quickly, compared to a larger company that might move more slowly on getting approval for a new hire. The first day probably won’t be full of excitement, but you’ll likely learn some basic details about the company and your place in it. &lt;/p&gt;

&lt;p&gt;First day checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I know my direct supervisor and who else to turn to for help.&lt;/li&gt;
&lt;li&gt;I have access to whatever I need to perform my job (at least for the next day).&lt;/li&gt;
&lt;li&gt;I understand my process for starting, working on, and completing a task (often, this could simply be moving a JIRA ticket from the to-do section to done).&lt;/li&gt;
&lt;li&gt;I am as prepared as I can be to start the next day of work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h6tV5Tfl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3z8ycg689jj152cqw5ju.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h6tV5Tfl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3z8ycg689jj152cqw5ju.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  First Week
&lt;/h2&gt;

&lt;p&gt;Your first week will be a great opportunity to reach out and connect with a few of your teammates. If there are any extracurricular activities, like happy hours or company meetups, make sure to go! If there’s a teammate around your level who’s been there a little longer than you, reach out and ask what they would recommend you focus on to succeed (after all, they’ve most recently been in your position with this team). Your first week is also a great time to get a feel for what level of communication your manager is expecting. Make sure to give updates on the tasks you’re completing, and if they’re still reaching out about your tasks, it may be a sign that you should be communicating a bit more frequently.&lt;/p&gt;

&lt;p&gt;Whatever progress is made at this point, typically you’re still catching on to company-specific conventions and processes. Try to forgive yourself for any little mistakes that are bound to happen. During your first week,  it’s okay to make mistakes, as long as you’re learning from them. Also remember that, as a new part of the team, your work speed is important but not the most important variable of your job performance. I had conversations with my supervisor about how accuracy, independence, and then speed were important, and typically in that order. So don’t sacrifice one higher priority item for another, and always be aware of where you are putting your energy.&lt;/p&gt;

&lt;p&gt;First week checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I’ve tuned or optimized my dev environment for my position. Reach out to coworkers for tips on this one!&lt;/li&gt;
&lt;li&gt;I’ve gathered company resources (such as handbooks, PR guides, etc.) in case I have questions.&lt;/li&gt;
&lt;li&gt;I know who I can pair with on any problems I’m facing (you’d be surprised what experienced developers can teach you within the span of 15 minutes).&lt;/li&gt;
&lt;li&gt;I’ve reached out to coworkers for advice they wish they had when they first started here (and why not add some of them on LinkedIn?).&lt;/li&gt;
&lt;li&gt;I am periodically checking other employee’s work (i.e. pull requests) to see what coding patterns they use and what could be considered good or bad code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TcwxcThz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j7ikv90lwpam0segtknr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TcwxcThz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j7ikv90lwpam0segtknr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  First Month
&lt;/h2&gt;

&lt;p&gt;Around the close of my first month, I started to feel like a strong part of the team, but don’t be discouraged if it takes a little longer. At this point, you’ll probably be fully onboarded and set up for success. And really, the best thing about the first month is that it’s when you start to see growth. You’ve learned company processes, and now dividends are paying off for having a growth mindset and learning from setbacks. &lt;/p&gt;

&lt;p&gt;Even though you seem to be establishing yourself within the team, don’t forget to focus on basics such as testing the functionality of your work and communicating effectively with your teammates. During my first month, I started to focus more on speed of development rather than accuracy and ultimately paid for it with pull request rejections. I then had to dig through non-working code to fix the issues, which can be a difficult process, especially compared to creating something correctly the first time. &lt;/p&gt;

&lt;p&gt;First month checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I’m starting to feel confident that I’m a valuable part of the team.&lt;/li&gt;
&lt;li&gt;I’m asking for feedback on work when I’m not getting a clear understanding of what’s going on with my code.&lt;/li&gt;
&lt;li&gt;I’ve started picking up smaller tickets of my own accord (as long as they’re within your scope of work).&lt;/li&gt;
&lt;li&gt;I’m starting to feel comfortable in areas of the codebase where I previously may have felt confused or lost on what was going on.&lt;/li&gt;
&lt;li&gt;I’m still welcoming code reviews and working on not repeating mistakes that have been commented on previously. (Your managers will notice this!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WSp4rG_v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3k4gcws3uid8b2pbe316.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WSp4rG_v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3k4gcws3uid8b2pbe316.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Onward and Upward
&lt;/h2&gt;

&lt;p&gt;By now, you will certainly know if you’re excelling or still need to make minor adjustments. Take the time to revel in the fact that you’re doing exactly what you want to do and getting compensated to do it! It’s a long road to get where you are, and it shouldn’t be taken lightly. Continuing to grow and develop your skill set will be important moving forward, but if you’re providing value by this point, you’re on a good path.&lt;/p&gt;

&lt;p&gt;Remember to focus on the things you can control and that no hire is perfect. If you follow some of the core principles of this guide, you’ll have plenty of resources to work with on your journey, and your journey certainly doesn’t end here. Everyone on a team was the new hire at some point, and as time goes on, you’ll probably laugh at the nervous thoughts you had leading up to your first few days. Just know that no one here wants you to fail, and your coworkers want to enjoy working with you. Keep improving, don’t listen to thoughts that make you feel like you don’t belong, and you will certainly be just fine.&lt;/p&gt;

</description>
      <category>onboarding</category>
      <category>jobs</category>
      <category>junior</category>
      <category>developer</category>
    </item>
    <item>
      <title>Providing a Rewarding Software Internship</title>
      <dc:creator>Stormi Hoebelheinrich</dc:creator>
      <pubDate>Thu, 30 Apr 2020 20:16:07 +0000</pubDate>
      <link>https://forem.com/olioapps/providing-a-rewarding-software-internship-2h84</link>
      <guid>https://forem.com/olioapps/providing-a-rewarding-software-internship-2h84</guid>
      <description>&lt;p&gt;There are many paths into software. Some start a career right out of college, some self-teach in the evenings for years, others smash away at intensive summer boot camps, and some seem to roll into this world with a penchant for technology. For a lot of us, it’s a combination of these. Eventually, we transition into the professional side of software (though it sometimes doesn’t feel like it at the time). Maybe that means getting hired to build a website for your uncle's small business, starting an internship or apprenticeship, landing a full-time gig in a fancy office, or somewhere in between. &lt;/p&gt;

&lt;p&gt;For me, it was an internship fresh out of a boot camp with a small but mature company in Portland, Oregon. It was an experience, though imperfect, I’m immensely thankful for. Shortly after completing my brief internship, I was hired by Olio Apps, a Portland-based software consultancy. As a company, Olio Apps focuses on building web and mobile apps, but as a team, we’re encouraged to focus on personal development through skill-building and sharing. One way we do this, while also giving back to the development community, is by occasionally offering internships to junior developers. We’ve seen several rounds of interns, and each time, we learn something new and refine the process. This year, I was given the opportunity to lead the internship. Thanks to careful planning, the support of the whole team, and two excellent interns, I’ll be the first to report it was a smashing success. &lt;/p&gt;

&lt;p&gt;Internships can come in many shapes and sizes, and can have mixed results for the interns as well as the company. There are a lot of factors to consider when planning to host interns, such as company size, senior developer availability, project complexity, intern skill level, etc. Some factors can be controlled, and others can’t. But there are a few things that can help maximize the value of the internship both for the interns and the company. If you or your company is considering offering an internship in the future, or already has an internship program, here are some of my top tips.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing Interns
&lt;/h3&gt;

&lt;p&gt;To find interns, we typically work with a local code school, Epicodus, and are given 10 or so junior developers to interview. We have quick, speed-dating-like interviews that are 30 minutes long. For us, it feels like seconds. But for them, most of whom are experiencing their first ever technical interviews,  I’m sure it feels like hours. The code school then does the final match-making based on both the interviewers' and interviewees' responses. Because of this process, we don’t get the final say in who our interns are, but for the most part, we’ve had good luck with getting our top choices. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_c_vT_PI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/a81f900af3888346aa4efb207bbaf581/0a251/interview.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_c_vT_PI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/a81f900af3888346aa4efb207bbaf581/0a251/interview.jpg" alt="Two people in an interview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At Olio Apps, we kind of make a holiday of the intern interviewing and selection process, pausing our work to meet the interns and talk about how the interviews went. We involve the whole team in meeting and selecting the interns because team cohesion is an important part of our company culture. Based on our collective experience working with different types of people, we coined our ideal candidate “the humble ass-kicker.” We look for someone who is the right combination of cultural fit and skills (or perceived ability to obtain skills). That may seem obvious to some, but it can sometimes be tempting to lean toward someone who has impressive hard skills but lacks in personality, or vice versa. From experience, we’ve learned that a blend of hard and soft skills is essential, especially because there’s a lot of collaboration and pair-programming encouraged during the internships we offer. If someone isn’t easy to work with, it’s difficult for everyone. &lt;/p&gt;

&lt;p&gt;It can be challenging to get a sense of a junior developer’s skills and personality during a brief 30-minute interview. We do about 5 minutes of “meet the whole team,” followed by 10 minutes of non-technical, cultural fit questions, and then dedicate the final 15 minutes to a collaborative whiteboarding exercise. Whiteboarding can be intimidating for junior developers, but it gives us an opportunity to see how they operate under stress, how they solve problems verbally and visually in real time, and how they ask questions and engage with team members. It also gives them a taste of a real-world technical interview, which is good for their professional development. After the 30 minutes are up, one of our team members usually offers to take them for coffee to answer any of their questions and decompress after the interview. Interviewing is always a two-way street (though sometimes it doesn’t feel like it as a junior developer), and it’s important to us to make a good impression with the internship candidates. &lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-Internship Planning
&lt;/h3&gt;

&lt;p&gt;Having a plan for the internship is vital. Through our years of offering internships, there has always been a rough plan that includes a few lectures, practice problems, toy apps, and eventually test writing and basic tickets in various real-world projects. This time was different. As the internship facilitator, I created a structured (yet flexible) five-week plan that would provide a guide for the interns, as well as me, while I navigated taking on this new role and continued to fulfill my other roles as technical lead for &lt;a href="https://www.shoutbase.com"&gt;Shoutbase&lt;/a&gt; and architect on other projects. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YRxvLTc_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/916af9c09bc0ac7de84a0bd54d530620/0a251/planning.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YRxvLTc_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/916af9c09bc0ac7de84a0bd54d530620/0a251/planning.jpg" alt="planner with sticky notes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The plan included a one-week ramp-up of JavaScript skills, which included reading materials, coding exercises, code review, and topic lectures. After the ramp-up, they were introduced to the Shoutbase code and the detailed tech design I had created for the feature we would implement together. I took the challenging parts while they started taking from an organized set of tickets. Starting small, they worked on writing unit tests for stateless utility functions, similar to what they had seen in coding exercises the week before, followed by writing different stateless utility functions themselves. After that, they moved to writing simple React components. By week three, they were writing progressively more challenging React components and integrating reusable existing components. After that, they added functionality to their components using our in-house rendition of Redux called &lt;a href="https://github.com/olioapps/sitka"&gt;Sitka&lt;/a&gt;. By the end, they got to experience the end-of-sprint testing, debugging, and bug-fixing cycle. &lt;/p&gt;

&lt;p&gt;Having a detailed tech design and a structured plan of attack was critical to the success of the internship. It helped me communicate what I needed from them and eliminated any confusion around basic things (like what to name a certain function) as well as more major things (like state management and expected behavior). It also allowed me to step away and work on other duties while remaining confident that they could work independently and deliver what was expected, even as juniors. &lt;/p&gt;

&lt;p&gt;Maintaining flexibility was also key. Each week had its own set of goals that could be fine-tuned based on the week before. Throughout the internship, we focused on learning and writing quality code, rather than stressing over hard deadlines. This gave everyone room to make mistakes, enjoy the experience, and learn. &lt;/p&gt;

&lt;h3&gt;
  
  
  Involving the Whole Team
&lt;/h3&gt;

&lt;p&gt;Beyond an introduction to writing code in a professional environment, a primary feature of an internship is exposure to senior developers. That way, interns get to hear different perspectives around programming, working in the industry, and tips and tricks. While I was the primary facilitator for the internship, each Olio Apps team member had their moment to shine by delivering a talk in their area of interest or expertise. The talks gave a primer on new subjects or expanded on what the interns had learned in code school. In all, there were over a dozen talks that included our company's philosophy for writing code, tooling to enhance productivity, pull request etiquette, ES6 syntax and conventions for clean JavaScript code, writing unit tests, advanced CSS and styling techniques, React, Redux-Saga, Sitka, frontend and backend architecture, sprint planning, QA, and manual testing. &lt;/p&gt;

&lt;p&gt;The talks served many functions. Of course, they helped teach the interns skills they could then apply to their work, but it also gave the team members an opportunity to stretch themselves. While preparing for their talks, many of them refined their own understanding of certain topics and had to take on the beginner’s mindset, in order to simplify complex ideas into their simplest forms. It’s a challenging but rewarding task. In addition to that, junior developers often ask great questions that can spur conversation and even challenge senior developers' understanding. &lt;/p&gt;

&lt;p&gt;We also recorded these talks. By recording them, the information could be shared internally amongst current and future team members. Instead of siloing information into a few “topic experts,” we can now create a bank of tribal knowledge of which we all share. And having a set of videos geared toward junior developers is a great place to start. Additionally, we can share these videos with future interns and potentially externally as well, to spread our knowledge beyond the company. &lt;/p&gt;

&lt;h3&gt;
  
  
  Scoping a Project for Beginners
&lt;/h3&gt;

&lt;p&gt;At code school, the students become very familiar with creating short-lived projects from scratch. For us, it’s important to provide a more real-world experience for the interns where they can be introduced to a sophisticated, public-facing app. It’s also essential to create a safe playground environment, where the focus can be on learning without the potentially stressful pace or standards of client work. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SidTpLbG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/0f9a69d1d4bfddd4716aaa7cbe79055b/0a251/scope.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SidTpLbG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/0f9a69d1d4bfddd4716aaa7cbe79055b/0a251/scope.jpg" alt="eye glasses on a desk in front of a computer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The timeline for the internship lined up ideally with the introduction of a new feature to our internal project, &lt;a href="https://www.shoutbase.com"&gt;Shoutbase&lt;/a&gt;. I had already implemented the majority of the backend for the feature, and the interns ramped up just in time to help me start on the frontend. The UI was relatively complicated, including forms, state management, and communication with the backend—“not your average code school project,” to paraphrase one of the interns. One might say it was a relatively ambitious internship project. Despite this, the interns were able to complete a huge chunk of the feature, and they exceeded our original goals for the internship. &lt;/p&gt;

&lt;p&gt;The key was dividing the work into incremental pieces that the interns could understand and then progressively introducing more difficult tasks as their skills developed. While the end result of the feature was similar to how I (or another senior developer) would have written it, the path we took to get there was much different.&lt;/p&gt;

&lt;p&gt;Normally, when I’m planning to introduce a new UI feature, I will break up the feature into pieces and create tickets that consist of isolated chunks of end-to-end functionality. This includes any state management, utility functions, tests, styles, and behavior. I had the interns start in areas more familiar to them, like writing stateless utility functions and tests, which strengthened their skills in that area, and then we branched out from there. Breaking the work up in a way that allowed them to focus on the same type helped them gain mastery in an area before moving on. In the end, we could weave the pieces together into a working UI.&lt;/p&gt;

&lt;p&gt;The proverbial saying, “Measure once, cut twice,” is valuable philosophy for developers, but sometimes, it’s good for a junior developer to have to “cut” the same piece of code two or three times to understand the difference between “functioning,” “better,” and “best” code. There were a couple occasions where I provided a ticket with little guidance, reviewed the resulting code with a little more guidance, and then challenged the interns to try once again to take their code to another level. Though being asked to write the same piece of code over for the third time might be frustrating for some, a beginner with the right attitude is going to gain a lot of value from the experience and learn how to challenge their own code to reach a higher standard beyond being “done” or “functioning.” &lt;/p&gt;

&lt;p&gt;The first couple of weeks, I understood that I was spending more time reviewing and re-reviewing the interns’ code than it would have taken me to write it myself. But I also understood that the time I was taking to write out thoughtful critiques, provide links to further reading on the topics, and offer suggestions, rather than giving out all the answers, was an investment into developing their skills. And that benefitted me as well: in the final weeks of the internship, they were able to work relatively independently and deliver code that needed very little revision. &lt;/p&gt;

&lt;h3&gt;
  
  
  Defining a Workflow
&lt;/h3&gt;

&lt;p&gt;Creating a consistent workflow helped the internship run smoothly for everyone. From the interns’ perspective, the workflow was relatively simple. Each Monday, we would review the progress from the week before and plan the following week based on the master plan I created pre-internship, factoring in any necessary adjustments. For me, I needed to integrate the internship workflow into my other responsibilities. This was particularly challenging for the first couple of weeks, when the interns needed the most guidance. To help alleviate this, I created a schedule of black-out times when I was unavailable, and the interns would have to rely on each other or ask a different team member for help. This helped me get my own work done, and it also gave the interns the opportunity to interact directly with the other developers at Olio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WvgKUj1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/1004f03f9be71934b709b1122265af74/0a251/workflow.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WvgKUj1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/1004f03f9be71934b709b1122265af74/0a251/workflow.jpg" alt="man writing workflow on a whiteboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another important part of the workflow, beyond just slinging code, involved giving and receiving feedback. Feedback is essential for growth, and encouraging two-way feedback ensures that both parties are getting what they need and that the process improves over time. Each Friday, the interns were involved in our team’s weekly retrospective, which is an informal meeting where we reflect on the week, celebrating the highs and discussing solutions for any low points. By involving the interns in the retro, we gained insight into their experiences that helped us create a better internship for them and hopefully others in the future, leaning into the positive aspects and attempting to eliminate or mitigate any negative aspects. They also got to participate in one of my favorite rituals of the company, and hear the thoughts and emotions of more senior developers as we experienced and navigated through the highs and lows of creating software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Words of Caution
&lt;/h3&gt;

&lt;p&gt;After recently concluding a very successful internship, it’s easy to focus on the positive aspects, but I think it’s also important for me to address a possible downside that could impact both the company and the intern. Offering an internship can take a lot of resources. If you’re unable to front these resources, or if you think a low or unpaid internship is a good way of getting cheap code, think again. As I stated before, for quality results by the end of a several-week internship, significant investment by one or more senior developers is vital. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SKZyJyNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/ad7d651cab65f1a106953132f340b941/0a251/handshake.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SKZyJyNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.olioapps.com/static/ad7d651cab65f1a106953132f340b941/0a251/handshake.jpg" alt="Two people shaking hands"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Personally, I think offering an internship is a combination of two things: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an opportunity to give back to the developer community by giving the interns real world experience &lt;/li&gt;
&lt;li&gt;an opportunity to meet new developers as a trial period for possible hiring into your company&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of these opportunities involve having respect for the intern's time and effort, instead of seeing them as a resource for cheap code.&lt;/p&gt;

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

&lt;p&gt;By now, I hope it’s clear that offering an internship can be a valuable experience for everyone at a software company. Whether you’re considering taking interns for the first time or you’re a seasoned pro at hosting interns, hopefully, you feel inspired to provide an internship that strengthens your team, empowers junior developers, and gives value to everyone involved. If you’re interested in hearing more about internships at Olio Apps, check out this post by former interns and current full-time employees, Ami and Cory: &lt;a href="https://www.olioapps.com/blog/internship-experience/"&gt;Internship Experience&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>internship</category>
      <category>junior</category>
      <category>career</category>
    </item>
    <item>
      <title>Keep Calm And Carry On Coding: What to Do When Requirements Change</title>
      <dc:creator>Frank Meza</dc:creator>
      <pubDate>Fri, 06 Mar 2020 00:45:40 +0000</pubDate>
      <link>https://forem.com/olioapps/keep-calm-and-carry-on-coding-what-to-do-when-requirements-change-50mo</link>
      <guid>https://forem.com/olioapps/keep-calm-and-carry-on-coding-what-to-do-when-requirements-change-50mo</guid>
      <description>&lt;p&gt;Envision the following scenario: you are working away at the final 5% of a project, glad to be near the end, when you catch the first hints of unexpected changes coming in the near future.&lt;/p&gt;

&lt;p&gt;Your chat channel starts to fill up with innocuous phrases like "next iteration" and "looks good, now let's see how the users respond." It seems harmless, until you begin to receive successive waves of PDF files with pages upon pages of new requirements. “Huh…,” you might think to yourself, “this is turning into a completely different application!”&lt;/p&gt;

&lt;p&gt;If this is the first or second time you’ve experienced this, you might be somewhat new to the field of software development, and you may be feeling defeated. You want to feel that feeling of completion! Of crossing the finish line. It was so close. And now it appears so far away.&lt;/p&gt;

&lt;p&gt;How did this happen? People want to build software. They have a theory about what they want, and what their end users want. The perfect set of features, which will naturally be intuitive, simple and easy to use. But, it's just a theory. Once that theory is tested, it will most likely be only partially correct. That critical feature we built last month? We shipped it! It works perfectly. But, the users don’t understand it, and no one is using it. And so… the requirements will change. The goalposts will move.&lt;/p&gt;

&lt;p&gt;Here are some strategies to help you survive this lamentable, all-too-common predicament.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledge the Emotional Impact
&lt;/h2&gt;

&lt;p&gt;Late stage changes can brew a soul-crushing concoction of emotions.&lt;/p&gt;

&lt;p&gt;The first step out of this quagmire is to acknowledge that yes, you are frustrated. It's reasonable to be so. The code you've painstakingly engineered to match the original requirements might be critically maimed by "a few tweaks" in the 11th hour of the project. You feel stranded and overwhelmed. You start to wonder if life could have been easier if you had taken up a simpler career as a stuntman, or even as an astronaut.&lt;/p&gt;

&lt;p&gt;The next thing to do? Consciously choose constructive over destructive reactions to this distressing situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Say No to Destructive Reactions
&lt;/h2&gt;

&lt;p&gt;You may be tempted to wallow in self pity, or lash out in frustration. But this will only isolate you from the people you need to work with in order successfully navigate those changes. Succumbing to feelings of helplessness or inadequacy is likewise counter-productive, as that will blunt your ability to confidently rewrite or even discard code that no longer makes sense. Finally, a total emotional disengagement from the project may temporarily insulate you from feeling bad, but apathy will completely block you from any productive work until you get beyond it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grow by Facing Tough Times Head-On
&lt;/h2&gt;

&lt;p&gt;Try to adopt the mantra "I grow when challenged". Internalize that hard situations are invaluable for your growth as a software engineer.&lt;/p&gt;

&lt;p&gt;Consider an athlete who only trains with other, less capable athletes. While that individual may feel good about their performance, in reality they are capped at their present level of development. Similarly, a workplace devoid of significant and unexpected challenges will be a sterile and lifeless environment, which will stunt your growth as a professional problem solver.&lt;/p&gt;

&lt;p&gt;The path to becoming a better software engineer is a narrow one, full of rough patches and at times, very challenging terrain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tell Your Rubber Duck All About It
&lt;/h2&gt;

&lt;p&gt;Take a deep breath and step away from your computer. It’s time to make a fresh assessment of the situation, unencumbered by the weight of all that code you've written up to this point.&lt;/p&gt;

&lt;p&gt;First, gather up all the information relating to the requested changes. This might include the latest slide deck of changes, previous flow charts that you or a coworker has written, or scribbled notes and pinned chat messages.&lt;/p&gt;

&lt;p&gt;Once you've got that organized, the next thing to do is to try and explain to yourself what needs to be done in the simplest terms possible. Describe the present situation, the changes to be made, and the end goal. Using these thoughts as a guide, tour the regions of the system where changes are likely to occur. You might find that when you put a magnifying glass to them, those changes might turn out to be less pervasive than you initially thought.&lt;/p&gt;

&lt;p&gt;Finally, pick up a whiteboard marker and present your ideas to your peers. See if you can explain the problem and your proposed solution, using large, broad brushstrokes. Chances are, if you can articulate it, you've got a workable first draft solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practice Paired Planning
&lt;/h2&gt;

&lt;p&gt;Paired planning is a great way to see the changes through someone else's eyes. It's likely that your partner will have a different perspective, and come up with a novel approach, or bring up some edge cases you hadn’t considered. A taste test between several possible approaches is a great way to find a simple, efficient, and correct solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose Lo-fi When Designing
&lt;/h2&gt;

&lt;p&gt;During the planning phase, your goal should be to generate as many ideas for efficient solutions as possible. Don’t jump headfirst into coding. It's better to spend an hour outlining what you intend to do, explaining it to someone else, and clarifying your understanding. Whiteboard drawings, sequence diagrams, and high level design summaries can be some of your best tools during this process.&lt;/p&gt;

&lt;p&gt;With a whiteboard, you can virtually reimplement a system hundreds of times in the same duration it would take to incorrectly refactor the codebase once. The disposable nature of whiteboarding helps to not fall in love and commit to your first idea, which may not be the most optimal solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weigh the Scope of Changes Against Your Budget
&lt;/h2&gt;

&lt;p&gt;Before writing more code, ask the following questions to help guide the process of a refactoring a large software project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  How much tolerance is there in the project schedule? Can we make paradigm shifts, or should we fall back to bandaids until the next release? Can we ask for more time to "do the right thing"?&lt;/li&gt;
&lt;li&gt;  Given a tight delivery deadline, can the changes be quarantined to a particular layer of the application? For example, in the situation where the UI must change but it's too risky at this point to change business logic, one could build transformation logic to retrofit objects flowing between the UI and the business layers.&lt;/li&gt;
&lt;li&gt;  Given a more liberal deadline, which other parts of the codebase should we also improve, while we're in here making the essential changes?&lt;/li&gt;
&lt;li&gt;  Is this an opportunity to clean up the codebase? For example, could we delete logic which models a deprecated requirement? If the answer here is yes, could that be helpful in formulating part of the solution?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get Up and Take a Break
&lt;/h2&gt;

&lt;p&gt;It's always helpful to stop, take a break, and come back fresh. Move your body, and get outside of your own head for a short while. Do some jumping jacks. Pet a friendly dog. Go for a walk. Go get coffee, enjoy the outside air. Once revitalized, start coding with conviction, and you will prevail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accept that Change Is Inevitable In Living Projects
&lt;/h2&gt;

&lt;p&gt;It's several weeks later, and you've finally got a stable release. You matched the designs and the changes in functionality that they requested. Confidently, you submit your work for review. To your surprise, &lt;em&gt;they ask for even more changes&lt;/em&gt;. The cycle begins anew.&lt;/p&gt;

&lt;p&gt;Actually, this is a great thing! After seeing their vision come to fruition through your labors, and watching how end users react, your product owner better understands what they ultimately need. Based on what you delivered to them already, they can now see how much more is possible. It’s plainly obvious they trust you to make the next set of changes, since you've proven you're more than capable.&lt;/p&gt;

&lt;p&gt;So roll up your sleeves, and take the new challenge in stride. Carry on knowing that you are growing though the experience, and validating your ability to deliver software that is a living organism, always changing, always adapting!&lt;/p&gt;

</description>
      <category>software</category>
      <category>philosophy</category>
    </item>
    <item>
      <title>Legacies Never Die: How to Handle Legacy Code</title>
      <dc:creator>Ami</dc:creator>
      <pubDate>Thu, 27 Feb 2020 23:37:20 +0000</pubDate>
      <link>https://forem.com/olioapps/legacies-never-die-how-to-handle-legacy-code-21p7</link>
      <guid>https://forem.com/olioapps/legacies-never-die-how-to-handle-legacy-code-21p7</guid>
      <description>&lt;p&gt;When the term "legacy code" comes up, it's usually said or received with a tinge of disdain. A preliminary Google search for "legacy code memes" brings up hundreds and hundreds of image macros of people tearing their hair out, looking frazzled, or hugely disappointed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eyB8zuBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kesq9xlmnn7cg526mro1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eyB8zuBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kesq9xlmnn7cg526mro1.jpg" alt="Charlie from It's Always Sunny conspiracy meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I started working as a software developer 6 months ago, I had no idea what legacy code was or what working with it entailed.&lt;/p&gt;

&lt;p&gt;During my fourth month as a junior developer, I was asked to add a search filter modal to an app built by one of my coworkers two or three years ago. It seemed easy enough; I'd spent the majority of the last four months working on an incredibly complex app for another client involving our standard stack: &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;/&lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;/&lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt;/&lt;a href="https://redux-saga.js.org/"&gt;Redux-Saga&lt;/a&gt;. I had already solved many unique problems and felt confident in my coding ability enough to make a simple modal to pass query parameters to the backend.&lt;/p&gt;

&lt;p&gt;As you may have guessed, it wasn't nearly that simple. But why?&lt;/p&gt;

&lt;h2&gt;
  
  
  What legacy code is and why it can be challenging to deal with
&lt;/h2&gt;

&lt;p&gt;Legacy code is code inherited from another developer or team which uses older technologies that are no longer supported or have been superceded by a newer version. Many programmers say that "code becomes legacy code as soon as it's written". The functional difference between "regular" code and legacy code could simply be that it has different conventions compared to what you're used to working with.&lt;/p&gt;

&lt;p&gt;In my case, the app I was assigned to utilized &lt;a href="https://flow.org/"&gt;Flow&lt;/a&gt; rather than TypeScript, and it wasn't as strongly typed as I was accustomed to. This made it a bit harder for me to understand the structure of the data that was being fetched from the backend. No types  meant that I was running into TypeErrors on runtime much more frequently, which can be difficult to debug when you're writing a large feature. On top of this, the app used a much older version of React which needed to be reconciled with a compatible version of the component library I wanted to use to build the modal.&lt;/p&gt;

&lt;p&gt;Before I get into the nitty-gritty of how to handle legacy code with a sense of poise and rationality, I want to add a disclaimer that legacy code isn't all bad and working on a legacy project doesn't have to be terrible. On the contrary, working on legacy code taught me to be flexible, patient, and above all else, the experience allowed me the chance to solve problems with a new perspective in a novel context.&lt;/p&gt;

&lt;p&gt;In fact, it made me a better developer than I was before I started working through the aforementioned codebase, and hopefully your legacy project can teach you something too.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to deal with with legacy code on a technical level
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y2tRCFEr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f98nd83bj5fkwg2n6bxb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y2tRCFEr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f98nd83bj5fkwg2n6bxb.jpg" alt="Photo of old tools"&gt;&lt;/a&gt;&lt;br&gt;
Photo by Jeff Sheldon on Unsplash&lt;/p&gt;

&lt;h3&gt;
  
  
  Read documentation and code comments when possible
&lt;/h3&gt;

&lt;p&gt;In a perfect world, every codebase has a robust README that contains concise explanations of how the project works, code comments that explain the exact logic of the original author, and the whole application makes perfect sense. However, this is rarely the case. Many READMEs don't get updated as projects develop, people forget to write comments, assume that their logic is obvious to a new developer, or they simply run out of time to take care of those things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Look at the codebase as a whole
&lt;/h3&gt;

&lt;p&gt;If you're lost and don't know where to start, ask yourself these questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the app’s purpose?&lt;/li&gt;
&lt;li&gt;How does data flow through the app?&lt;/li&gt;
&lt;li&gt;How does your feature fit into the app?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you can get a sense of the big picture, it's easier to figure out how best to tackle the problem. Maybe you need to create a new file and create a new component. Maybe you need to write a utility function and test it. Whatever the case may be, understanding the broader context of your problem is a good first step to creating a solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test the app manually and with unit tests whenever possible
&lt;/h3&gt;

&lt;p&gt;Breaking an app temporarily while adding a new feature is an inevitability, no matter what level of developer you are. This is normal and expected, especially if you're new to the job, working in a legacy codebase with an unfamiliar stack, or some combination of the two.&lt;/p&gt;

&lt;p&gt;The best way to prevent these breakages from becoming long term problems is to test your app thoroughly with both unit tests and manual tests. Having these tests in place and knowing exactly what kind of coverage you get out of them will save you and future developers a lot of time. In addition, rigorous tests make the app more scalable and also give you a litte dopamine rush every time your tests run clean.&lt;/p&gt;

&lt;p&gt;For unit testing, you can use test frameworks like &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; or &lt;a href="https://jasmine.github.io/"&gt;Jasmine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For manual tests, you'll want to develop a test matrix and make sure the document is accessible to future developers. For the matrix, you'll want to define a set of actions, the expected behavior, the actual behavior when you test it, and any other details that are important, like so:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MqKaFhnu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7ey019c0uakeqvrd4aaz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MqKaFhnu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7ey019c0uakeqvrd4aaz.png" alt="Screenshot of a spreadsheet showing testing conditions and outcomes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll be covering how to implement both types of testing efficiently into your workflow in a future blog post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask for help
&lt;/h3&gt;

&lt;p&gt;Assuming your project was written by a current or former employee at your workplace, someone else probably knows what's going on in the app, or at least knows enough to get you unstuck. Learning to swallow your pride and ask someone else is a an uncomfortable step for some, but a necessary one for growing as a developer, and maybe your coworker can teach you a few new tricks.&lt;/p&gt;

&lt;p&gt;A good way to make efficient use of your time (and theirs) is to formulate informed questions. Try going back to looking at the codebase as a whole and figure out the gaps in your understanding. Not only will it help them to get a better sense of what your problem is, but it shows that you took the initiative of trying to solve the problem on your own first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Know when to cut your losses
&lt;/h3&gt;

&lt;p&gt;If you’re spending too much time trying to get your foot in the door and haven't made any serious stride towards implementing the feature after trying the steps above, it might be worth refactoring the code around your feature. Don't give up too easily, but also keep in mind what your deadlines are and what your project manager expects from you.&lt;/p&gt;

&lt;p&gt;That said, there are drawbacks to going about it that way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewriting code can introduce bugs, though this can be somewhat circumvented with good unit testing.&lt;/li&gt;
&lt;li&gt;Rewriting code can remove hidden functionality, though this can also be circumvented with good unit tests.&lt;/li&gt;
&lt;li&gt;If you're pressed for time, writing code outside of your feature in addition to your feature might actually be more time-consuming than just building around it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All in all, use your best judgement. There are pros and cons for either choice, and it's all dependent on your individual circumstances and project budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to deal with legacy code on a psychological level
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M4AwUZNK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cqz9qnj3ooott75fzfhq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M4AwUZNK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cqz9qnj3ooott75fzfhq.jpg" alt="A man sitting on a dock in a serene mountain lake"&gt;&lt;/a&gt;&lt;br&gt;
Photo by Simon Migaj on Unsplash&lt;/p&gt;

&lt;p&gt;Now that we've covered the technical aspects of dealing with legacy code, let's talk about how to deal with it using our soft skills. After all, developers are people, not just coding robots, and dealing with challenging problems on projects that require creativity and authorship can be emotionally taxing, not only for you, but for your coworkers as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Be humble and kind
&lt;/h3&gt;

&lt;p&gt;This is something that I will sheepishly admit I need to practice more. When I was first assigned the filter modal project, I was fairly vocal about how janky and unappealing the code was to deal with &lt;strong&gt;while the original author of the code was sitting 15 feet away from me.&lt;/strong&gt; I intended my comments to be a joke, but in hindsight I recognize that I was being arrogant and hurtful, and that I should have been more empathetic.&lt;/p&gt;

&lt;p&gt;There are a lot of factors that can lead to legacy code looking "off" which you should take into account before you start to criticize the author or assume the worst about them (This is loosely tied to the &lt;a href="https://en.wikipedia.org/wiki/Fundamental_attribution_error"&gt;fundamental attribution error!&lt;/a&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The original author may have had their reasons for writing code the way that they did.&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Time constraints and technology constraints can cause a person to write code that works but doesn't necessarily have the best convention. If you picture yourself in a situation with not enough time, outdated tools, and a todo list a mile long, you probably wouldn't write the best code either!&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Conventions change.&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In older Olio Apps projects, the convention for code is using single quotes to declare strings, and two spaces was equal to one tab. We had multiple small React components nested inside of a single file. In our current convention, we use double quotes and four spaces, and each React component, no matter how small, lives in its own &lt;code&gt;.tsx&lt;/code&gt; file in the &lt;code&gt;component&lt;/code&gt; directory. And in several years, I'm sure that will change too.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;All code eventually becomes legacy&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This ties back into the previous point: your code will eventually be legacy. As you move up the ladder of seniority, new developers will be hired on and will have to maintain your old code. You might write clean, flawless, DRY code, but once conventions change or trends change, those new developers might view your code the same way you view the legacy code of others.&lt;/p&gt;

&lt;h3&gt;
  
  
  Take pride in the small successes
&lt;/h3&gt;

&lt;p&gt;It’s not easy to work outside of your habitual conventions; there's a reason for the huge trove of memes and jokes about dealing with legacy code. If you've ever learned a language outside of your native tongue, you know how it feels to forget a word or term in your second language, but remember it in your native language and not be able to translate across the gap. The same goes for changing between modern and legacy conventions. Sometimes it just takes a minute to regain your bearings.&lt;/p&gt;

&lt;p&gt;In being able to successfully navigate legacy code, you're showing your ability to be adaptable, which is an important skill that benefits you at your current job and all of your future jobs, whether those jobs are in the technology field or not. Legacy code is the perfect playground to practice this skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use this time to bolster your own code writing
&lt;/h3&gt;

&lt;p&gt;Now that you've had the experience of working in a legacy codebase, you should come away from it with a better sense of what you like and don't like in terms of tools and conventions. These are things you can carry on with into future projects, and make you better at reviewing the code of others, offering constructive criticism, and giving mentorship.&lt;/p&gt;

&lt;h3&gt;
  
  
  Develop apps for the user &lt;strong&gt;and&lt;/strong&gt; the future developer
&lt;/h3&gt;

&lt;p&gt;Whether you've had the experience of great documentation and code comments or no documentation or code comments, you can see how both documentation and comments are powerful tools to help future developers navigate the project. You share a common goal of wanting a smooth, functional, and DRY app; maintaining the documentation and leaving behind informative code comments is a good way of bridging that gap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remember that your code will be legacy someday too
&lt;/h3&gt;

&lt;p&gt;I've mentioned this a few times already, but it's important to reiterate that your code will be legacy too, no matter how DRY and pristine your code and logic are.&lt;/p&gt;

&lt;p&gt;The most important takeaway is to be flexible, humble, and that you can definitely learn new tricks from old code.&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title> Love Thy Selenium Tests: Functional Tests that Fail Only When They're Supposed To</title>
      <dc:creator>Stormi Hoebelheinrich</dc:creator>
      <pubDate>Thu, 20 Feb 2020 18:41:33 +0000</pubDate>
      <link>https://forem.com/olioapps/love-thy-selenium-tests-functional-tests-that-fail-only-when-they-re-supposed-to-3kki</link>
      <guid>https://forem.com/olioapps/love-thy-selenium-tests-functional-tests-that-fail-only-when-they-re-supposed-to-3kki</guid>
      <description>&lt;p&gt;Automated browser testing with Selenium can be a developer's best friend, and at the same time, their worst enemy. Tests that once seemed to work well can mysteriously start to break, fail only sometimes, or slow to a crawl. But, your relationship with Selenium doesn't have to be so complicated. &lt;/p&gt;

&lt;p&gt;Trust and stability are paramount to maintaining a robust relationship with your test, and we've learned a lot of valuable lessons about cultivating a healthy partnership between the engineers and their tests while developing our flagship app, &lt;a href="https://www.shoutbase.com/"&gt;Shoutbase&lt;/a&gt;. We've compiled a list of practices that have helped us love our tests as much as we love our production code. &lt;/p&gt;

&lt;h3&gt;
  
  
  1. Ensure your tests are idempotent
&lt;/h3&gt;

&lt;p&gt;Testing is a matter of trust. You need to be able to rely on your test to run exactly the same way, getting the same result regardless of how many times it is run, either independently or part of a test suite. Without rigid consistency, your expected result becomes a moving target. When something goes wrong, it's considerably more challenging to isolate the issue when you don't know exactly what to expect in the first place. Additionally, tests that are allowed to affect others also share their problems. This can result in error leakages making it hard to find the root cause of an issue.&lt;/p&gt;

&lt;p&gt;Thankfully, enforcing idempotence can be achieved with a couple simple steps. First, start with a reliable state at the beginning of each individual test. Create a utility to setup this sanitized start environment. The utility should do things like logout, clear everything from storage such as cookies, auth tokens, or anything else your app might require to achieve a clean state. &lt;/p&gt;

&lt;p&gt;Second, take care to write self contained tests. While you might be tempted to use data from an upstream test as the setup for another, this should absolutely be avoided. You don't want future changes from upstream tests to break others. Instead, always create users and data points from scratch.&lt;/p&gt;

&lt;p&gt;Additionally, try to clean up after your tests, by deleting any data that might have been created at the end of each test. By containing the data within each test, you should be able to trust your tests will not impact each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Avoid using production code in tests
&lt;/h3&gt;

&lt;p&gt;As software engineers, we love reusing code. However, employing production code within tests can be dangerous. Even if you introduce functional testing into your project toward the end of the development cycle, your code will likely undergo significant future changes. Altering a piece of production code used heavily throughout your tests can cause gnarly ripple effects, including error leakages, and make it harder to determine where problems lie. This can cause confusion among your testing concerns. Are you testing a utility you imported, or are you testing something in the UI?&lt;/p&gt;

&lt;p&gt;API client code is perhaps the most tempting to import and reuse within tests. But again, this should be avoided. Instead, create test utility functions to make raw API calls, that will not be subject to as much iteration and change as the production code.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Avoid using selenium to test everything
&lt;/h3&gt;

&lt;p&gt;Selenium tests the UI, and should be reserved for end-to-end user interaction tests. Selenium can be slow and cumbersome at times, especially when you've employed these strategies to ensure stability. You don't want to slow your test suite further by using Selenium to check a sorting function works correctly when a faster unit test could do the trick. &lt;/p&gt;

&lt;p&gt;For background functions the user doesn't see, such as utilities and client functions, you should use other testing suites and keep these concerns separate.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Fail fast
&lt;/h3&gt;

&lt;p&gt;As stated before, Selenium tests typically take longer to run due to setup and browser latency issues. There are a couple key ways to reduce this burden. &lt;/p&gt;

&lt;p&gt;First, avoid programming long pauses and excessive retries. This will only extend the run of a problematic test. Sometimes sleeps and retries can be useful to help your tests handle problems outside of your code, such as browser or webdriver issues. However, keep in mind these are expensive and should be used sparingly. They can also cover up race conditions, which can come back to bite later.&lt;/p&gt;

&lt;p&gt;Next, always throw an error as soon as there is a problem. Do not allow the test to move on to the next step. Not only is the runtime of the selenium tests costly, but equally expensive is the amount of time you might spend wading through layers of cascading test failures looking for the root cause.  &lt;/p&gt;

&lt;h3&gt;
  
  
  5. Collect Data
&lt;/h3&gt;

&lt;p&gt;When a test fails, the developer transforms into a detective. Collecting evidence is key to efficiently and effectively finding the bug. When it comes to issues that surface on the UI, the potential sources of error are great. Not only is the frontend code suspect, but also the backend, the browser, and potentially the testing framework itself. These are the key pieces of evidence we collect when debugging test failures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;log reports from the backend &lt;/li&gt;
&lt;li&gt;javascript console log&lt;/li&gt;
&lt;li&gt;screen shots of the browser the moment a test fails&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  6. Keep tests DRY and well documented
&lt;/h3&gt;

&lt;p&gt;Maintainability is just as key in your tests as it is in your production code. Your tests are a living document, and are therefore a tax. The same techniques you use for writing good code can be applied to your tests to make it easier to pay the tax as the production code evolves.&lt;/p&gt;

&lt;p&gt;First, keep your tests DRY to achieve maintainability. Speed up the writing and refactoring process by making use of utility functions to handle repeated tasks.&lt;/p&gt;

&lt;p&gt;Second, keep each test scoped to a single concern. Avoid testing code or behavior already tested elsewhere. As an isolated piece of production code changes, you don't want to find yourself having to fix several different tests. &lt;/p&gt;

&lt;p&gt;Third, take care to document your test code. You can use a self documenting framework such as cucumber, or add comments to document the intent of each test. Documentation significantly decreases the amount of time it takes to untangle the intent of a test, and makes it easier for you or someone else to refactor your code later. It can also help you get an idea of your testing coverage, or how much of the functional UI code is tested. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusions
&lt;/h3&gt;

&lt;p&gt;We believe for every user-facing interface, functional testing is essential. Over time, we have honed our techniques to make Selenium tests robust, easy to maintain, and even enjoyable to write. There are some common, avoidable pitfalls that can make functional tests a nightmare. We hope you can follow these tips and watch your tests run like a dream. &lt;/p&gt;

</description>
      <category>testing</category>
      <category>selenium</category>
      <category>philosophy</category>
    </item>
    <item>
      <title>Faster Iteration with Mock APIs</title>
      <dc:creator>Scott Becker</dc:creator>
      <pubDate>Thu, 06 Feb 2020 22:28:09 +0000</pubDate>
      <link>https://forem.com/olioapps/faster-iteration-with-mock-apis-4mcb</link>
      <guid>https://forem.com/olioapps/faster-iteration-with-mock-apis-4mcb</guid>
      <description>&lt;p&gt;We frequently work on front-ends along side other teams building APIs. Sometimes those APIs are not yet available. But deadlines and sprint demos are approaching. Are we to sit around twiddling our thumbs? Nope!&lt;/p&gt;

&lt;p&gt;The approach we take is to get the API spec if available, or if not, imagine how we would want this API to look and behave.&lt;/p&gt;

&lt;p&gt;Then we create mock API functions &lt;em&gt;within&lt;/em&gt; our front-end application that do not make any requests, but behave exactly as if calling the real API, returning fake data.&lt;/p&gt;

&lt;p&gt;An alternative is to use a hosted fake API server like &lt;a href="https://github.com/typicode/json-server"&gt;json-server&lt;/a&gt;. In some cases, that might be a better choice - such as if the front-end is deployed to a staging site, and you want to be able to edit the fake responses without redeploying.&lt;/p&gt;

&lt;p&gt;During the development phase, we prefer to use mocking functions instead, so we don't increase our dependencies or have to rely on an external service for testing.&lt;/p&gt;

&lt;p&gt;This allows us to decouple our development process from that of other teams we are relying on, and quickly put together working demos that illustrate how the application will perform once the API is online.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example API - a list of tips
&lt;/h2&gt;

&lt;p&gt;Suppose our backend API will return a set of "tips". A tip is a short piece of content, to show to a user on start up. Think &lt;em&gt;Clippy&lt;/em&gt; or, a "Did you know? ..." pop-up. The front end application will fetch these tips from the API and show them to the user.&lt;/p&gt;

&lt;p&gt;We have mockups, but the API is still under development. Fortunately, the shape and contract of the API is known. If we build the UI to be data driven now, we won't have to go back and do partial rework later. When the API comes online, we can flip a switch and it should "just work".&lt;/p&gt;

&lt;h2&gt;
  
  
  API response shape
&lt;/h2&gt;

&lt;p&gt;This API will exist on an authenticated HTTPS endpoint. Let's say its &lt;code&gt;GET https://special.api/tips&lt;/code&gt;. According to the spec, the response JSON shape will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tips"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"info"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Set a daily or weekly reminder to track your time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"subtitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tracking"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Over time, we can provide insights and suggestions for improvement"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://url/to/set-reminder"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Add Reminder"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tips&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Static Typing
&lt;/h2&gt;

&lt;p&gt;At Olio Apps we've been enjoying &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; lately, which allows us to create static types for things like this json structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// the tip itself&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ApiTip&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// the api response envelope, an object that has an array of tips&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ApiTips&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;tips&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApiTip&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Immutable Data
&lt;/h2&gt;

&lt;p&gt;Note the use of &lt;code&gt;readonly&lt;/code&gt; and &lt;code&gt;ReadonlyArray&amp;lt;T&amp;gt;&lt;/code&gt; which enforce immutability. We use &lt;a href="https://github.com/jonaskello/tslint-immutable"&gt;tslint-immutable&lt;/a&gt; to ensure all data types are immutable and checked at compile time, instead of at run time with something like &lt;a href="https://github.com/facebook/immutable-js/"&gt;Immutable.js&lt;/a&gt;. This yields higher performance and more straightforward code.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Client
&lt;/h2&gt;

&lt;p&gt;The following function makes a request to fetch tips:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getTips&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HandledResp&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;useMock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fakeGetTips&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;handleResp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buildUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/tips&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authHeader&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;handleResp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;handleResp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Mock API Function
&lt;/h2&gt;

&lt;p&gt;Note the &lt;code&gt;useMock&lt;/code&gt; check. If this configuration variable is &lt;code&gt;true&lt;/code&gt;, we'll call &lt;code&gt;fakeGetTips()&lt;/code&gt; instead of making a request.&lt;/p&gt;

&lt;p&gt;Here's what &lt;code&gt;fakeGetTips()&lt;/code&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fakeGetTips&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Resp&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApiTips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;tips&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Set a daily or weekly reminder to track your time&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;subtitle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tracking&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Over time, we can provide insights and suggestions for improvement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://url/to/set-reminder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add Reminder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="c1"&gt;// more fake tips&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like a standard request, &lt;code&gt;fakeGetTips()&lt;/code&gt; return a promise that resolves to a standard response object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Resp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Standard Response Handling
&lt;/h2&gt;

&lt;p&gt;In both versions, when the response value comes back in a promise, we handle it with &lt;code&gt;.then((res: Resp) =&amp;gt; handleResp(res))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;handleResp&lt;/code&gt; function converts the response object into a normalized structure, where any text from the response is parsed as json and returned as &lt;code&gt;items&lt;/code&gt;, along with the &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;statusText&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleResp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Resp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;HandledResp&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// if text present, parse as json, otherwise empty array&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="c1"&gt;// return normalized response object&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;HandledResp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// can be any javascript type&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All downstream functions can now rely on &lt;code&gt;items&lt;/code&gt; to be the response data, converted back into a javascript object. Once the &lt;code&gt;tips&lt;/code&gt; API comes online, we can simply change &lt;code&gt;useMock&lt;/code&gt; to false, and it should work as long as the API data structure hasn't changed.&lt;/p&gt;

</description>
      <category>api</category>
      <category>mocking</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>"The Value of Code Documentation"</title>
      <dc:creator>Frank Meza</dc:creator>
      <pubDate>Fri, 31 Jan 2020 23:02:24 +0000</pubDate>
      <link>https://forem.com/olioapps/the-value-of-code-documentation-1kg4</link>
      <guid>https://forem.com/olioapps/the-value-of-code-documentation-1kg4</guid>
      <description>&lt;p&gt;Code documentation is the collection of easy to understand images and written descriptions that explain what a codebase does and how it can be used.&lt;/p&gt;

&lt;p&gt;It can be simple explanatory comments above functions and blocks, or a full-fledged developer handbook, complete with prescriptive style dos-and-don'ts, overviews of each part of the application, and approaches to the most common types of coding tasks.&lt;/p&gt;

&lt;p&gt;It's often best to find a happy medium between these two extremes when you make the conscious decision to comment your code and outline the gnarlier areas of a codebase in plain language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why document your code?
&lt;/h2&gt;

&lt;p&gt;Why go to the trouble writing &lt;em&gt;about&lt;/em&gt; your code, instead of just &lt;em&gt;writing&lt;/em&gt; code? Wouldn't that just be more productive anyway?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yxEpy-sW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/5914687/34965265-a6b6f904-fa07-11e7-92ff-22729040dd0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yxEpy-sW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/5914687/34965265-a6b6f904-fa07-11e7-92ff-22729040dd0a.png" alt="condescending wonka meme" width="495" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mental Save Points
&lt;/h3&gt;

&lt;p&gt;Documentation is like a mental save point for those times when you finally get what's going on at the end of the day and don't want to lose momentum. Well documented code will ensure that when you need to dive back in tomorrow morning (or several months from now), you won't have to take as much time getting up to speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Documented code gets reused
&lt;/h3&gt;

&lt;p&gt;The difference between a used library and an unused library  often comes down to its documentation.&lt;/p&gt;

&lt;p&gt;Who wants to use an undocumented open-source library or contribute to an undocumented project? Almost no one.&lt;/p&gt;

&lt;p&gt;In most cases, you'd rather use a less powerful library that has docs. Why? Because the documentation conveys other points of information about a codebase. The developers believe that the project is worth the time and energy to write about it in plain language so anyone who might be interested can quickly get started and learn how it works, and why key decisions were made.&lt;/p&gt;

&lt;p&gt;Finding a new, interesting, and well-documented project in your favorite language can be very exciting and fun. Let's look at the extreme alternative: being required to use an undocumented code library and potentially contribute to a seemingly byzantine codebase... it sounds pretty painful, right?&lt;/p&gt;

&lt;p&gt;So why haven't you documented your own code?&lt;/p&gt;

&lt;h2&gt;
  
  
  Documenting code is part of writing good code
&lt;/h2&gt;

&lt;p&gt;A cornerstone of good code is maintainability, achieved through understandable, legible documentation.&lt;/p&gt;

&lt;p&gt;There are multiple ways of documenting code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;choosing good names for variables and functions&lt;/li&gt;
&lt;li&gt;leaving brief comments within the code to help give context to future readers&lt;/li&gt;
&lt;li&gt;adding illustrative images such as sequence and entity relationship diagrams&lt;/li&gt;
&lt;li&gt;providing API docs, describing each class, method, argument and return value&lt;/li&gt;
&lt;li&gt;using a statically typed language, such as TypeScript (types as documentation)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Compare two examples
&lt;/h2&gt;

&lt;p&gt;Let's say you're getting some data from a backend API and "ingressing" it - converting it into a more useful shape for a front-end UI. Here's the first of two possible solutions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// wdgt.js&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;converter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wdgtHdr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastTS&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wdgtDtl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;dtlId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dtlId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;dtlName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dtlNm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;openTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;closeTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cTS&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wdgtRev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;revs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prsn1Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prsn1Ln&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prsn1Fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cTS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;assocId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prsn1Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;assoc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prsn1Fn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prsn1Ln&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;note&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;revTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rr&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;wdgtHdr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wdgtDtl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wdgtRev&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code has the potential to be &lt;strong&gt;painful&lt;/strong&gt;. You can see by the name that this is some sort of converter that takes &lt;code&gt;w&lt;/code&gt; as its param.&lt;/p&gt;

&lt;p&gt;It looks like it returns a header, maybe details, and something called revs. Where did revs come from, anyway? Of course, there's no details about the incoming variable names &lt;code&gt;note, prsn1Id, prsn1Ln, prsn1Fn, amt, cTS&lt;/code&gt;... or is there? Is &lt;code&gt;rr&lt;/code&gt; short for &lt;code&gt;returned rev&lt;/code&gt;? Who can say.&lt;/p&gt;

&lt;p&gt;Let's look at the second example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// widget_utils.ts&lt;/span&gt;

&lt;span class="c1"&gt;// widgetConverter :: widgetRespDTO -&amp;gt; widget&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;widgetConverter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;widgetRespDTO&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Widget&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;widgetHeader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WidgetHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastTS&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// timestamp&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;widgetDetail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WidgetDetail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgetId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dtlNm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;openTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// timestamp&lt;/span&gt;
        &lt;span class="na"&gt;closeTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cTS&lt;/span&gt; &lt;span class="c1"&gt;// timestamp&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// [WidgetRevisionsRespDTO] is nested inside of WidgetRespDTO&lt;/span&gt;

    &lt;span class="c1"&gt;// [WidgetRevisionsRespDTO].map -&amp;gt; [WidgetRevision]&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;widgetRevisions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WidgetRevision&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nx"&gt;wResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;revs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;wRevs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WidgetRevisionsRespDTO&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;WidgetRevision&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// how that other team names their variables...!&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prsn1Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prsn1Ln&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prsn1Fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cTS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wRevs&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cmt&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;associateId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prsn1Id&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;associateName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prsn1Fn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prsn1Ln&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;amt&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;revisionTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cTS&lt;/span&gt; &lt;span class="c1"&gt;// unix timestamp, and "closeTS" fyi&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;associateId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;associateName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;revisionTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;widgetHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;widgetDetail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;widgetRevisions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow, how different! This function is in a &lt;code&gt;util&lt;/code&gt; file, so the main file is less cluttered already. It's also written in TypeScript instead of plain JavaScript, so we have the benefit of type definitions to help guide us.&lt;/p&gt;

&lt;p&gt;We're converting &lt;code&gt;widgetRespDTO&lt;/code&gt;s into &lt;code&gt;widget&lt;/code&gt;s. Though shortened, we have full knowledge of what &lt;code&gt;wResp&lt;/code&gt; is. We're creating a &lt;code&gt;widgetHeader&lt;/code&gt;, and a &lt;code&gt;widgetDetail&lt;/code&gt;, that's easy to see. We also understand what &lt;code&gt;oTS&lt;/code&gt; and &lt;code&gt;cTS&lt;/code&gt; are. We can tell &lt;code&gt;WidgetRevisionsRespDTO&lt;/code&gt;s are nested inside of &lt;code&gt;WidgetRespDTO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Someone very kindly renamed the incoming variables so &lt;em&gt;everyone&lt;/em&gt; who sees this code knows what they are. Finally, we see a &lt;code&gt;Widget&lt;/code&gt; must be composed of the returned &lt;code&gt;{widgetHeader, widgetDetail, widgetRevisions}&lt;/code&gt; object, since it must match the return type &lt;code&gt;Widget&lt;/code&gt; specified at the top.&lt;/p&gt;

&lt;p&gt;Which code would you feel better about using?&lt;/p&gt;

&lt;h2&gt;
  
  
  Who benefits?
&lt;/h2&gt;

&lt;p&gt;Well documented code benefits many people:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Junior developers
&lt;/h3&gt;

&lt;p&gt;Because it's in plain language and easy to understand, documentation helps junior developers and new team members feel confident jumping into a codebase. This prevents frustration and early abandonment of a task because it gets too complicated too quickly.&lt;/p&gt;

&lt;p&gt;It's also helpful for junior developers to write their own documentation so they can share their code with others and so they can get a better understanding of their code.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Senior developers
&lt;/h3&gt;

&lt;p&gt;By taking the time to document now, senior devs spend less time explaining their code to others in the future.&lt;/p&gt;

&lt;p&gt;They can also write more complex code. Plain language documentation lets others use it like a black box, without having to understand the inner workings.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Teams &amp;amp; open source projects
&lt;/h3&gt;

&lt;p&gt;Personnel changes can bring a tremendous slowdown to a project. Up-to-date and well documented code can serve as insurance against such slowdowns and allow the remaining team members to take a step back, review the code from a high level and decide on the best course of action moving forward, and if needed, on-board new employees.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. You
&lt;/h3&gt;

&lt;p&gt;When documenting code, you must summarize it. In order to summarize properly, you must be able to understand it, holding the different parts in your head at the same time. Writing or contributing to the documentation is a shortcut to really understanding a codebase, making huge contributions, and feeling like a great part of a great team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good documentation can DRY up our coding experience
&lt;/h2&gt;

&lt;p&gt;As a programmer you've probably heard of the &lt;em&gt;Don't Repeat Yourself&lt;/em&gt; principle as a key to writing clean and concise code. Instead of repeating the same code block several times, write a function that can be written once and employed all over your application.&lt;/p&gt;

&lt;p&gt;In the same way, you and your team shouldn't be running into similar problems and then reinventing the wheel each time you attempt to solve them. For example, have you ever heard one of your coworkers or found yourself saying:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Agh, I solved something very similar to this but I never remember how I do it when it comes up... I should probably write it down somewhere, huh?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You then find yourself scanning the same Stack Overflow threads again and again.&lt;/p&gt;

&lt;p&gt;Save yourself and your coworkers this grief by following the spirit of the DRY principle and writing a document that you can employ every time the issue comes up! This will help you and others on your team save time, and be more effective in writing simpler, more manageable, and more efficient code.&lt;/p&gt;

&lt;p&gt;How has code documentation, or the lack thereof, affected you?&lt;/p&gt;

</description>
      <category>documentation</category>
    </item>
    <item>
      <title>Rapid Prototyping Native Mobile iOS and Android Apps in 5 minutes with React Native and Expo</title>
      <dc:creator>Scott Becker</dc:creator>
      <pubDate>Wed, 01 May 2019 21:21:44 +0000</pubDate>
      <link>https://forem.com/olioapps/rapid-prototyping-native-mobile-ios-and-android-apps-in-5-minutes-with-react-native-and-expo-2hfm</link>
      <guid>https://forem.com/olioapps/rapid-prototyping-native-mobile-ios-and-android-apps-in-5-minutes-with-react-native-and-expo-2hfm</guid>
      <description>&lt;p&gt;When you have a new idea for an app, you want to get feedback from users as quickly as possible to see if the idea has legs, and start refining it. The best feedback comes once people try it.&lt;/p&gt;

&lt;p&gt;So, our primary goal is to make it possible to get real user feedback from people using the app as soon as possible.&lt;/p&gt;

&lt;p&gt;In this post, we'll begin creating an app and make it possible to share it with others within 5 minutes so they can give you feedback as you build it.&lt;/p&gt;

&lt;p&gt;Secondary goals&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native App - not a responsive web app running in the browser, a fully native app&lt;/li&gt;
&lt;li&gt;Skip the app stores - getting an app approved in the app stores is an involved, time-consuming  process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given these goals, one of the best sets of tools available today is React Native and Expo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; is a declarative, efficient, and flexible JavaScript library for building user interfaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://facebook.github.io/react-native/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt; is a framework for building native iOS and Android apps using React.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://expo.io/" rel="noopener noreferrer"&gt;Expo&lt;/a&gt; is a tool for creating React Native apps quickly. With Expo, you can start a new app, preview it in the browser, then see it on your own device, and share it with others almost immediately (5 minutes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Get a taste with Snack
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.olioapps.com%2Fassets%2Fimages%2Frapid-prototyping-react-native-expo%2Frapid-prototyping-react-native-expo-snack-640.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.olioapps.com%2Fassets%2Fimages%2Frapid-prototyping-react-native-expo%2Frapid-prototyping-react-native-expo-snack-640.gif" alt="Snack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://snack.expo.io/" rel="noopener noreferrer"&gt;Snack&lt;/a&gt; is a lightweight online IDE for Expo that allows you to run code in the browser in a matter of seconds. It's great for quick experiments and sharing examples.&lt;/p&gt;

&lt;p&gt;Go to &lt;a href="https://snack.expo.io/" rel="noopener noreferrer"&gt;snack.expo.io&lt;/a&gt;. You'll see some code, and an image of an iPhone, with a large "Tap to play" button. Tap it, and the app will boot in a device simulator.&lt;/p&gt;

&lt;p&gt;Change the text in the code and it will update.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the Expo toolchain
&lt;/h2&gt;

&lt;p&gt;First, install &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;. The latest version is recommended.&lt;/p&gt;

&lt;p&gt;Second, install the Expo package for Node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;expo-cli &lt;span class="nt"&gt;--global&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third, install the expo mobile app on your device. Either &lt;a href="https://itunes.apple.com/us/app/expo-client/id982107779?mt=8" rel="noopener noreferrer"&gt;iOS&lt;/a&gt; or &lt;a href="https://play.google.com/store/apps/details?id=host.exp.exponent&amp;amp;hl=en_US" rel="noopener noreferrer"&gt;Android&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a new app
&lt;/h2&gt;

&lt;p&gt;Once everything is installed, you can run the following commands from your terminal to get a new app running in development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;expo init my-new-project
&lt;span class="nb"&gt;cd &lt;/span&gt;my-new-project
expo start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Scan app QR code to run it on device
&lt;/h2&gt;

&lt;p&gt;You will see a QR code in terminal and Dev Tools. To open your project on your device, simply scan the QR code with the Expo Client app on Android or using the built-in QR code scanner of the Camera app on iOS.&lt;/p&gt;

&lt;h2&gt;
  
  
  See your changes immediately
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Edit the home screen &lt;code&gt;screens/HomeScreen.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Watch your device refresh&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Notice what we did not do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No Apple developer program registration ($99 + days)&lt;/li&gt;
&lt;li&gt;No creating code signing certificates&lt;/li&gt;
&lt;li&gt;No cable from the computer to the device&lt;/li&gt;
&lt;li&gt;No compiling in Xcode&lt;/li&gt;
&lt;li&gt;No uploading to TestFlight&lt;/li&gt;
&lt;li&gt;No inviting users to TestFlight&lt;/li&gt;
&lt;li&gt;No app store review process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, we will want to do these things too, but only when we are ready to launch. By that time, we will have validated and improved our idea with real user feedback so it can be truly great.&lt;/p&gt;

&lt;p&gt;And we won't have to start over with a different platform or framework to get there. React Native and Expo supports the full life cycle from development to app store deployment.&lt;/p&gt;

&lt;p&gt;Do you need an app prototyped or built fast? Olio Apps can help. We have built and shipped multiple iOS and Android apps to the app store. &lt;a href="//mailto:sayhi@olioapps.com"&gt;Tell us about your project!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rapidprototyping</category>
      <category>mobile</category>
      <category>reactnative</category>
      <category>expo</category>
    </item>
  </channel>
</rss>
