CLI Have No Idea What I’m Doing: Planning (and Building) My First CLI Application

60 days into my Flatiron bootcamp and the first project—a CLI application—is due in a few hours.

Looking back over everything I learned, all the parts needed to build a CLI app were covered, but the idea of building something from scratch was still intimidating.

Yes, we had built CLI apps as part of the course material, but this was different. The safety net of a test suite or being able to hit the ask a question button was missing, this time.

That, in addition to the unknown of how much time it would take to build had me feeling anxious.

if anxiety == unknown
     puts "screams into the void"
end

Luckily, anxiety caused by the unknown can be resolved by planning and presenting yourself with facts instead of “what ifs”. So, planning felt like a logical first step to tackling this project. This post will cover the planning steps I took to get started, related resources and thoughts on what I would like to implement in the future.

Planning

I was very tempted to jump right in. To get ahead of the clock. But just like grocery shopping without a list leads to disastrous results, making a list of what skills, tech and methods I need would help me to stay focused and avoid being surprised.

In my case, there were specific project requirements so I started there. Reading over the requirements, making notes and asking a question if needed was the first step. I did this before writing any code.

Even if you do not have project requirements, think about what you want your CLI app to do. Here are some questions that came to mind for me:

  • What is the purpose of the program? What will it do?
  • What outside resources or data will it need?
  • How will the user interact with the CLI?
  • Will it take any inputs from the user?
  • What outputs should it have?

For my application, I wanted to display data showing burger restaurants (or restaurants that sold burgers) nearby.

Programmatically, this is what I want to happen.

  1. Get all local burger restaurants
  2. Display name, rating, and location
  3. Prompt user to input a restaurant
  4. Display more information

It doesn’t have to be perfect, just enough to the core concepts across. This also helped me to avoid scope creep with my own project.

Relating to technology, I knew I needed a website to scrape data from (as part of the project requirements) and settled The 15 Best Places for Burgers in Baltimore on Foursquare. I choose this page because the source code had well-named CSS classes that would make it easy to target and scrape the sections I needed.

I wanted to use Bundler to set up the project and Nokogiri to do the actual scraping, so took the time to read through their documentation. For me, reading documentation (and project requirements) in detail helped to ease my anxiety, feel prepared and maximize my time.

At this point, I was ready to start coding.

Building the CLI

Getting the skeleton of my project was the very first step. At first, I wasn’t sure which files or folders were best practices. Then, the Bundler documentation made it very easy to get started.

In the terminal, all you have to do is the following:

bundler gem name_of_your_project

For my project, it looked like this:

bundler gem burger_finder

Small note that I learned the hard way. Ruby uses snake case as a naming convention. While bundler gem burger-finder isn’t wrong…it does make for weird folder formatting, so it’s best to stick with snake case.

At this point, I will admit, I felt stuck. While I knew how to build the methods I would need to create the parts of my CLI, I did not know how to get the CLI its self to work. Or, what all these mystery files that Bundler created are for. So, as opposed to muddling my way through it, I read Dissecting my Ruby Project Skeleton which I found helpful in understanding the parts I was working with.

Once I could get my program running via ruby bin/start in the command line, I was good to start building my methods and chaining them together as needed.

For the most part, building the pieces went smoothly. However, getting the pieces to work together while returning the correct data did take some work. Setting up a console so that I can peak into the code (like with binding.pry) instead of running the whole program was helpful too.

My biggest blocker was getting 403 errors when scraping my webpage. Understandably, I had been flagged for hitting the site too often in a short amount of time.

As a workaround, I created a static version of the main page for the initial scrape (since I would be hitting that one the most) but will go out to the venue’ specific page for the details. A quick search showed the following as a fix that so far, as kept a 403 error from happening when scraping the detail pages.

Nokogiri::HTML(open(url, 'User-Agent' => 'ruby'))

The Future

Earlier, I mentioned scope creep as something I wanted to avoid. I find it easy to want to do all-of-the-things when its best to focus on the basic requirements first, then refactor and add features afterward.

That said, I here as some of what I would like to add to this project in the future:

  • Implementing an API: It turns out Foursquare’s Places API is perfect for this! Getting set up was easy and free but I did not have enough time to implement it before my project due date. Understanding the API and how to manipulate and display the data is on my to-do list.
  • Location by input: I’d also like to get location data from the user via input so that I can display more relevant restaurant information. Again, the Places API would be perfect for this, but there may have been a way to append a zip code to a URL which would be used to scrape data. For example, www.fourquare.com?search=burger?zip=90201 would display burger joints in Beverly Hills.
  • Edge cases. Right now, my application assumes the user will only enter correct inputs. In a real-world application, this is not realistic. I’d like to include messaging that responds to an input that is outside of the available range. For example, if the user wants to know about the 20th restaurant object when there are only 15.
  • Error Handling. Custom error messaging was covered briefly in our course material, but I would like to explore it more. If something was broken how can I communicate that with a user? Error handling ties into the edge cases I mentioned above.

Conclusion

Overall, I am happy with how my burger_finder project came out. It’s not perfect, true, but I implemented a lot of what I learned in the past two months. It’s weird to think that earlier this year, I had never written a line of Ruby.

Now, I’m not far off from being able to create a program from scratch and publish it as a gem. I’ve gotten better at troubleshooting errors, debugging and making progress even when it feels like I am stuck or out of time.

Now that my project has been submitted, it’s time to sit back, reflect and prepare for the project review.

Maybe I’ll grab a burger for dinner. Is there an app for that?

Taking Note

Recently, I realized the importance of—good—notetaking.

I’ll admit that I’ve done this more than once.

My attitude toward note-taking used to be “If I don’t remember it, it must not be that important”.

Yikes.

This may have worked in an art college, were sketches and concepts were common. But, as I’ve moved deeper into the software engineer side of the track, remembering specific processes gets a lot harder.

For one, it’s not just the concept that needs to be recalled. But how.

Are you using Ruby or Javascript? The concept to get a random item from an array may be the same in both languages, but the syntax will be different. What about the output, what format should it be in? Or, does this need to account for an argument?

These are some of the things that come to mind when writing code that is similar to something that I’ve done before, but I can’t remember how I got there.

If I could dump the memory space in my brain currently occupied by every song lyric in Hercules, maybe I could remember all of the things, but for now, I’ll stick to taking better notes.

Here’s what worked for me.

Literally, Write Comments in Your Code

I’m probably not the only developer in the world that assumes future you will remember what your code does. This may be true in the short term, but long term (days, weeks, hours, etc) is a different story.

To combat this, I literally explain to myself, in the comments, what each line of code is doing.

Here’s an example using a method that randomly generates a new hex color each time it is run.

def createColor
  hexadecimalIntegers = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"] # Lists all possible integers that can be use in a valid hex code
  color = hexadecimalIntegers.sample(6).join("") # Randomly get 6 items from the hexadecimalIntegers array, then join them together at each character
  "Your new hex color is ##{color}" # Puts hex color
end

When writing comments, I like to think about how I would explain my code to someone else. I could go a step further and add a note explaining why I used .sample in place of .rand.

Write Notes by Hand

I will admit, I’ve debated if this is the route I wanted to go myself. I keep a bullet journal for to-dos but writing code by hand seemed silly when it’s so easy to copy and paste from one digital document to another.

There are studies that support pen and paper note-taking over typing, so I decided to give it a try.

My head was spinning when it came to classes in Ruby. It was a new concept with a lot of moving parts. I wanted to make sure I understood the core concepts before I moved onto the advanced parts.

When going back to review classes in Ruby, I reread the course material and took pen and paper notes. Any key concepts that I find myself forgetting—I’m looking at you instance variables—I would write it down. Similar to my inline comments, next to the code snippet, I would include in plain English what the function does in relation to the bigger picture.

Taking notes by hand, forced me to keep my notes concise and focused. Notes like this, paired with my inline notes, were helpful when comes to refactoring, which brings me to my next point.

Review and Refactor Often

Do you ever solve a problem, then feel like you don’t know what you actually did?

Perhaps it’s a side effect of wanting to learn a lot in a small amount of time. But, I’ve realized that I am better off taking the time to review the code, notes, and comments I wrote previously before moving onto new concepts.

This is where refactoring comes in.

Refactoring is a new concept to me, but I see it as improving the existing code while maintaining it’s functionality.

Usually, my inline comments present enough of a story that I know what problem the code was meant to solve, to begin with.

Then I can refer to my handwritten notes—which cover the broader concepts—to see where I can make improvements.

For example, are there variable names that I can clarify? Is there any redundant code that I can remove? Are there edge cases that my code should account for?


In closing, making an effort to write good notes can be a game-changer in your learning journey.

While written notes, supplemented by inline code comments works for me, it is important to use whatever note-taking format—written, typed, audio—works best for you.

How do you like to take notes when learning a new programming concept?

Asking for Help as a Developer

Uh oh.

Your code doesn’t work and you have no idea why.

Congratulations! Developer achievement unlocked!

Hitting a wall because of broken code with (seemingly) no solution in sight will happen at least once during your career as a developer.

And that’s ok.

The idea of running into a problem that you cannot solve is not meant to scare you. In fact, I mean for it to be the exact opposite. Knowing how to troubleshoot, when and how to ask for help is a valuable skill as a developer.

Here’s a short guide on how to ask for help in a way that concisely moves you toward a solution.

Be specific about your problem

When presenting your problem to ask for help, realize that someone outside of your codebase may not know what you are working with, which may make it difficult to offer solutions.

Some questions to ask yourself before presenting a problem include:

  • What were you expecting to happen?
  • What did happen?
  • What have you already tried and what was the result then?

Include details like operating system, browser or framework if it is relevant. Anything that may help someone else have an idea of is going on. That way, they have a good understanding of where you are, what you are working and how to jump in to help.

Share your code

If you can—please keep sensitive information in mind—share a snippet of your code. For someone trying to help, it is helpful to know exactly what code you are working with. With a code sample, they can quickly look for common gotchas like misspellings or syntax errors. They may also use your code to try and recreate the problem locally and test possible solutions.

Sharing full sections of code is ideal. If it a larger project, push your code to some place like Github and share the link to your repo. Mention which files, functions or lines of code you are currently having problems with.

For example, you may say that the math on your howManyDaysUntilHalloween function is off in the spooky.js file. This way, whoever is helping you can get right to the problem instead of searching your codebase and hoping they found the one they think you were referring too.

For smaller projects, sharing a single file or function is fine. If you can, attach the code as a text file or formatted as code. This way, the formatting remains intact and the code can easily be copy-pasted. If you are getting any specific error messages, you can share those as code snippets too.

What have you already tried?

Have you tried turning off and on again?

Why yes. Yes, I have.

Debugging, just like knowing when to ask for help is another key skill of being a developer. When you run into unexpected behavior, take a step back and spend a little bit off time trying possible solutions before asking for help.

If you are able to find a solution on your own, great! You can stop reading this guide and keep coding. Otherwise, you can share what you have tried and the results.

For example, if your code was working before, what was added recently that may be breaking it? What functionality were you trying to add?

Removing the most recent code additions—or temporarily commenting it out—may help you to see exactly where in the program it is breaking. Are you getting no output when there should be one? Or, are you getting an output but it’s not the result you were trying to achieve?

While you are debugging, make note of what you have tried, if it worked, kind of work, or didn’t work and share those with your code when you are asking for help. That way, your helper can skip over suggestions you have already tried and guide you in the right direction.

Ask questions

Thanks to your helper, your code is working now! Cool.

But, now that it is working…do you understand what went wrong in the first place? Or what the fix is actually doing?

Part of being a developer is learning from your mistakes. If you can, ask if your helper can explain what the problem was so that it can be avoided for future builds. They may be able to explain the why and why not’s behind a concept in a way that makes more sense in the context of your project. Consider asking if they have any resources they would recommend for further reading.

This is also a great time to take notes. Add comments to your code so that future you knows what each line of code is doing and why.


In summary, running into a problem you cannot solve is not the end of the world, even if it feels like it. By taking the time to analyze the problem, presenting it in detail with supporting code and expectations you can get the help you need in no time.

Documenting for Open Source

Thanks for attending my talk Documenting for Open Source at Write the Docs Portland. Slides, recording, resources and other fun stuff can be found here. The presentation is being recorded so check back later for the video!

As always, Tweet—and use the conference hashtag #writethedocs—or email me if you have questions!

Project Files

How Many Days Until Halloween? – The project that started it all! Not sure how many days until the spookiest day of the year? No worries, this webpage will do the counting for you!

Fork the project files on Github – Peak behind the code and see firsthand how this project evolved over time. Contributions are always welcome!

Presentation Slides [6 MB] – A PDF of my presentation slides can be downloaded here.

Resources

  • Hacktoberfest – Hacktoberfest is a month-long celebration of open source software
  • Open Source Guides – An extensive collection of resources for individuals, communities, and companies who want to learn how to run and contribute to an open source project
  • Open Source Survey – The Open Source Survey is an open data project by GitHub and collaborators from academia, industry, and the broader open source community
  • Bridget Kromhout’s Tweet on writing docs with empathy
  • Make a Read Me – A 101 guide to creating a README
  • Contributors Covenant – A boilerplate code of conduct for open source projects
  • Keep a Changelog – One of the many ways to structure your changelog
  • Documentation Guide – A living, breathing doc about writings docs from Write the Docs

The One Where 2018 Comes To An End

via GIPHY

In the moment, it can be difficult to realize what you’ve accomplished in a year.

2018 is no different.

As the year comes to a close, I wanted to reflect on everything that I accomplished—or didn’t—in the past 365 days.

Continue reading “The One Where 2018 Comes To An End”