Rockin' good code, rockin' good times

Text

In late January I began an optimistically-paced series of blog posts on challenges faced by apprentice developers. Today I’d like to pick back up with a focus on improving tech-specific knowledge.

Originally I explained:

“There are going to be a lot of tools and methods with which new programmers are unfamiliar or not as capable as necessary. For instance, I’ve spent a significant portion of my first three weeks improving my understanding of test-driven development using mocks, stubs, and libraries that aid in this process (eg VCR for API calls).”

After three months on the job, I can say even more confidently that this is a huge challenge faced not only by apprentices, but by all developers (though it is certainly a more difficult challenge for newcomers). We must be vigilant to keep up with new technological developments, regardless of whether the updates are for the language we write, the tools we use, or new apps being launched. It is the job of a developer to determine the best tool for the job and subsequently, to develop an awareness about what tools are available.


Apprentices are in the unique position of having a comparatively tiny set of  tools so we need to work as quickly as possible to learn the tools for our job. To this end, I have two suggestions: practice, and focus.

Practice is THE way to learn about new tools. The power of learning by doing cannot be overstated. Whether you are struggling to learn a new language or tasked with integrating a new API, the most effective way to improve will be using the tool you need to master.

There are several ways to do this. The most obvious is learning as you go. This is generally an efficient use of time, but often circumstantial pressure requires a more expedient solution. In this case, I recommend a “breakable toy” which allows for practice without the pressure of clients or management.

Note that reading documentation, watching videos, and going to meetups are all important additives, but prioritize them as supplements and not your primary method of practice.


The second recommendation I have involves focus. The limitless possibilities afforded by coding make being an apprentice extremely exciting. There are literally an infinite number of topics to discover and explore, all of which could help you grow into a knowledgeable software craftsman.

However, this benefit of code as a career can have the unfortunate side effect of distracting the novice programmer. It’s very easy to try investigating so many topics that you spread yourself too thin and end up impeding both your learning and your productivity. Realize that as an apprentice, any learning you do will be beneficial, and that it generally makes sense to focus on the topics that also make you a good employee. This might be difficult if you work for a consultancy, but for any other apprenticeship, become the best you can be with the tools and languages used by your employer and stem your curiosity on other topics until you’re more proficient at what you use daily.

When you practice regularly with appropriate focus, you end up growing at a more rapid rate. Ultimately you’ll prove yourself to your employer quicker, and be able to hasten your pace of learning by training on the topics with which your mentor can assist.


Stay tuned next time for the final post in this series, which will focus on company-specific challenges and wrap up with any miscellaneous advice for apprentices

Text

If you’re interested in becoming a better software developer, there are well worn paths and pedagogical methodologies that can get you there. You can go to school, find a mentor, write code, get involved in open source, get a job — all of these are accepted ways to improve your skills.

I’m not here to talk about any of them. This is the first post in a series where I’m going to explore interdisciplinary paths to improving your skill as a software developer.

Why You Should Read Books Unrelated to Programming

Writing software is an act of communication, and through reading we are exposed to different modes of thinking and communicating ideas.

Through reading and expanding our vocabulary and understanding of humanity we can improve the quality of our communication in code as well as in our everyday interactions.

If you agree that naming things is one of the hardest problems in computer science, then you need tools in your arsenal to describe the abstractions we’re asked to create every day. There’s no better way to do that then to expand your vocabulary by reading more books.

What You Should Read

Read the classics of fiction, paying special attention to their narrative arc and the way they use language to bring the story to life. It will serve you well when you need to name your next class or method.

Read complex Russian literature that requires you to keep track of characters with multiple names, uncertainty in outcomes, and unclear motives. It will serve you well when you have to understand complex code interactions and architectures.

Read non-fiction about psychology, sociology, or any field that engages with humanity that you’re ignorant of. It will challenge your world view and expose you to ideas you don’t come across in your everyday life. This can help build empathy for your end users and other software developers as you appreciate the breadth of human experience and approaches to understanding the world around us.


The best software developers I’ve worked with have a broad range of interests outside of the field, and being well read is a consistent theme. Broaden your horizons and read more books unrelated to software.

Text

Let’s say we’re testing a conditional rule that has three parts. The method looks something like this:

def all_good?
    a == 1 && b == 2 && c == 3
end

There are technically 2^3 = 8 branches there, since each variable can take on a value that is or is not equal to the value specified, and allow the rest to vary. The naive approach may looks something like this:

context "when a = 1" do
  context "when b == 2" do
    context "when c == 3" do
    context "when c != 3" do
  context "when b != 2" do
    context "when c == 3" do
    context "when c != 3" do
context "when a != 1" do
  context "when b == 2" do
    context "when c == 3" do
    ...

This is obviously absurd but sometimes while we’re testing, we get 3 levels deep into a conditional and don’t recognize that we’re actually repeating this pattern. It’s much less obvious to spot with real world code. 

Here’s a shortcut: all you have to do is test the case when all the conditions are satisfied, and then provide a single context for each sub-condition to prove that when it’s not met, the entire rule fails:

context "when all conditions are met" do
    let(:a) { 1 }
    let(:b) { 2 }
    let(:c) { 3 }
    
    it { should be_all_good }    
    
    context "when a != 1" do
        let(:a) { 99 }
        it { should_not be_all_good }
            
    context "when b != 1" do
        let(:b) { 99 }
        it { should_not be_all_good }

From 8 conditionals, down to 4. That’s pretty good! And much more readable, without all that nesting. If you had 4 pieces to the conditional, you go from 16 branches to only 5.

Happy testing!

Text

I’m a framework geek. I love it when someone takes complex ideas and distills them into simple, visual structure. So when Eric Ries’s Lean Startup book came out a couple years ago, packed to the gills with simple frameworks, I was like: This is my jam. I want to work with people who think like this.

I started designing for startups shortly after that and eventually made my way Reverb.com, where I’ve had the opportunity to put some of the lean startup principles into practice.

Since reading Eric’s book I’ve bought all the other lean startup books, read all the blog posts, and downloaded all the slide decks filled with tips. And so I was downright giddy when Eric became an investor in Reverb this past fall and invited us to the lean startup conference. Do you see a pattern here? I’m a compulsive framework collector. I’ve been slow to share my own lessons learned though. So here’s my first cut at that, and my first cut at writing words on the internet that are not part of a UI design.

I’m going to create a series of these based on what we’re doing at Reverb called Frameworks FTW. Here goes.

Principle 1.
If you’re not focused on the speed at which you learn, then you’re doing it wrong.

Lots of people think startup success is all about speed. Ship code. SHIP code. SHIP CODE. It’s definitely about speed, but the speed you should be focusing on is the speed at which your organization learns.

Dan Milstein from Hut 8 Labs gave an excellent talk on this idea at the conference. Here’s his clever “math” for why creating an information-seeking organization matters. Hang on to your hats. I’m about to go 9th-grade geometry on you here and format this like proof. Admittedly, I may have gone a bit overboard.

image
Lesson Learned:
The rate at which you gather information + make decisions serves as a proxy for the speed at which you’ll generate revenue. The faster you learn what works, the faster you’ll make money.

Ok yes, ACTUAL revenue is measured in dollars. But you only make dollars if people are buying your product. And people don’t buy your product if you haven’t gained an understanding of how to make it work for them.


Do you remember the oft-repeated lean startup maxim “get out of the building”??? All that geek-math above illustrates why it matters.

It’s not enough to do this once or twice. You have to create a culture that values learning in this way so you sustainably ship meaningful features and products. Your engineers don’t like talking to customers? That’s a problem. Your designers don’t watch people use their designs? That’s a problem.


At the lean startup conference, I learned how Meetup.com creates space for engineers and designers to quickly see how customers react to their ideas. They recruit people to come in for UX and concept testing before they even know what they’re going to test!?! People come in for these sessions 5 days a week! Moderators walk the participant through a prototype while engineers and designers watch/listen via video and screen sharing. If they have a question for the researcher to ask the participant, they live chat it to them right in the moment. They flip “get out of the building” on its head and bring the people to their office, creating a constant stream of insights. Here’s the simple visual for this:

image
Lesson Learned:
Reduce the amount time between someone on your team wondering how customers will use your product and knowing how they will use it.

Bonus Tip: If you don’t have the resources to recruit and bring research participants to your workplace: Go here, plug in a url, and get a free five minute video of someone using your product: http://peek.usertesting.com/. I’m told you can do three of those per month.


At Reverb, we don’t have the resources to do what Meetup does. However, we do have a small team almost entirely composed of the exact target audience for our product, and we’re co-located with the biggest user of our platform. So when the product team needs to understand how someone might interact with a new design, we can walk across the room or down the hall and put it in front of someone, watch them interact with it, and start learning. And if something breaks, you can bet we hear about it almost immediately.

Lesson Learned:
Reduce the distance between you and your customers by hiring employees that use your product on a daily basis and locate your office near your customers.

Another way we gain valuable insight from customers is by using software to help us send personal follow up emails at key moments.

Some examples: A customer starts creating a listing on Reverb but stops short of publishing it to the marketplace — they get a follow up email asking them if they need any help finishing the listing. A few days after they join the site — they get an email welcoming them and asking for feedback. They joined and made 3 sales in a row — they get an encouraging note to keep selling and tips on how to become a better seller. Each of these interactions gives us a chance to make our business personal and make people feel like the valued customer that they are.

By distributing different follow up emails across the team, everyone has the opportunity to learn from customers. If every customer interaction goes through customer service, other team members lose touch with the problems experienced by customers. You rob your team of hearing about pain points and you rob your business of having many brains thinking about how to solve issues.

Lesson Learned:
Have every employee connect with customers in personal ways to distribute learning and get all team members thinking about how to solve problems.

That’s the first principle and a few lessons learned in the Frameworks FTW series. If you like simple visuals and want to catch all of the posts, follow this blog and follow me on twitter.

If you’re a front-end developer (especially if you’re a musician) you should come learn with us. Apply at jobs.reverb.com.

Text

Two weeks ago I outlined a number of challenges faced by apprentice (or other first-time) developers. The very first of these hurdles is new concepts and code standards, my description of which is below:

…wrangling with philosophical concepts that are either completely foreign or understood only in theory…(e.g.) the Law of Demeter, command-query separation, separation of concerns, and other SOLID principles.”

Today I’d like to elaborate on this challenge and provide some advice for both new apprentices and their mentors on how philosophical code concepts can be best learned and understood.


For apprentices, I have three recommendations regarding immersion, repetition, and feedback. The first suggestion, immersion, is self-evident, but important enough to state explicitly:

In order to learn as efficiently as possible, you really have to study (and I mean this in the traditional sense of the word) programming concepts regularly. I like to take time at the beginning and end of my day to check any blog posts shared in HipChat or on Twitter. I also read regularly outside of work. Reverb’s dev team meets weekly to discuss programming literature over lunch, which helps supplement my regular self study with expert opinions and anecdotes. Overall, I make sure that I’m constantly engaging with the dev community to keep up with both historical and current programming concepts.

This segways naturally into the second recommendation I have, which can be distilled down to one word: repetition. In order to transform described concepts into engrained knowledge, you need to apply these theories to your code.

This is actually easier said than done when you are working on projects that you don’t choose yourself. I try to find one thing that speaks to me and keep that in the forefront of my mind for a couple days. It’s only after implementing written rules in your own code that it truly begins to become second nature. For this reason, be aware that (depending on the concept) it may take a while before you can find a place to implement a particular strategy. I encourage you to bookmark articles to revisit them later and take notes when reading books so you have something to review in a couple weeks. Reviewing past literature will help you gauge your progress; an important part of growing from apprentice to journeyman.

The last suggestion I have regards feedback. While studying and applying new concepts and code standards to your work, it is easy to become isolated from the most important aspect of your growth: personal feedback. Open yourself to criticism; it is the best catalyst for learning. If possible, discuss your takeaways regularly with colleagues. Not only will this challenge your interpretations of your reading, it will also reinforce what you’ve read and help you adapt new concepts to your style of programming.


On the flip side, assisting mentors as they learn high level concepts can be a challenge. Too little help and an apprentice may develop incorrect practices or standards that aren’t aligned with the rest of the team. Too much information, however, can overwhelm an apprentice and impede the rate at which they learn. Mentors need to allow for appropriate pacing; rushing through literature for volume doesn’t allow for the knowledge to ‘sink in’. Encourage your apprentice to read and, if possible, read along with them and discuss the described concepts together. This will help you keep tabs on the apprentice and make sure they don’t wander astray.

That said, be patient. Expect repeated mistakes. It’s difficult to juggle multiple concepts at once when all are foreign. Try to focus on one area per week in order to make learning manageable. When critiquing code, address the area of focus as much as possible. This will help the apprentice learn by doing, but keep the criticism poignant enough that they don’t feel overwhelmed.

Finally, engage in empathy. This is universally important, but when dealing with an apprentice, its relevance is tantamount. Criticism is extremely helpful, but make sure your feedback is specific, actionable, and kind.


Welp this turned out to be far longer than I intended originally. Stay tuned for my next post, which will focus on improving tech-specific knowledge and the difficulty this might give a first-time developer.

Text

Ten weeks ago I graduated from an intensive programming course called Dev Bootcamp and three weeks ago I began working for Reverb as their first apprentice web developer.

Being new to both my company and my profession, I’m in a uniquely challenging position that most experience only a few times in their lives. To start, there are hurdles that all developers face upon joining a new company. These include:

  • Familiarizing yourself with organizational conventions (e.g. for naming, file/folder structure, styling)

  • Codebase format, connectivity, and tools (eg libraries, deployment practices, proprietary scripts)

  • Company culture and chain-of-command

  • Company policies (e.g. hours, meetings, lunch)

Most professional developers are mindful of the chaos that comes from beginning a new job, but sometimes it may be hard to recall the complexity of acclimating to code as a career. There are several obstacles unique to newbie developers. Some examples:

  • New concepts and code standards

First-time developers are likely wrangling with philosophical concepts that are either completely foreign or understood only in theory. I’m talking about the Law of Demeter, command-query separation, separation of concerns, and other SOLID principles.

  • Improving tech-specific knowledge and comfort

There are going to be a lot of tools and methods with which new programmers are unfamiliar or not as capable as necessary. For instance, I’ve spent a significant portion of my first three weeks improving my understanding of test-driven development using mocks, stubs, and libraries that aid in this process (e.g. VCR for API calls).

  • Reverb-specific: VIM!!!

This is self-explanatory, but switching to Vim from TextMate and Sublime Text is an often frustrating experience that slows development significantly (although I’m already beginning to realize the long-term payoff).

Over the next couple weeks I hope to elaborate on both the stresses sourced from these challenges and how I’ve managed (or failed to manage) them. My hope is that by exposing my ignorance and detailing my journey from apprentice to journeyman, I can inspire others wandering a similar path and assist mentors in training and empathizing with their mentees.

-Joe Levering, Apprentice Web Developer @ Reverb.com

Text

Here’s a thought experiment on removing complex conditionals from views. We haven’t done this fully at Reverb, so I’m just exploring it in this blog post to get some feedback.

My theory is that any usage of ==, &&, and || is problematic for our views (and actually, in all code outside the object in question), because it implies something that probably has a conceptual name, yet every person who has to read through the view code has to parse the conditional and understand what it means.

It’s more painful in views because those tend to be looked at by designers, which may not have intimate knowledge of the logic in question.

Let’s examine why these three things might be problematic:

Equality

payment.payment_type == 'credit_card'

The double equals implies knowledge of both sides of the equation. On the left hand side, if you’re asking about an object’s property, you assume knowledge of the types of values that property can take on. On the right side, you are assuming a particular value that may or may not be a true possible value. Here are steps we take to clean this up:

payment.payment_type == Payment::CREDIT_CARD
payment.payment_type?(Payment::CREDIT_CARD)
payment.credit_card?

The third variation is the most readable and hides internal implementation. You now have absolutely no knowledge about internal properties of the payment, nor of the possible values they can take.

Ands && Ors

There are a number of different types of boolean expressions that arise. Let’s first look at one where both parts of the conditional refer to the same object. In this case, we can condense it into one method on the same object:

Before:

auction.ended? && auction.loser?(current_user)

After:

auction.ended_and_user_lost?(current_user)

While the new method name is more verbose, I would venture to say that it’s more clear. Additionally, you are at less risk for someone copy-pasting bits of the original conditional and duplicating the logic. You have only one place that talks about losing an auction.

What about something that deals with two different objects? This is a common pattern at Reverb, where we often let admins and product owners do similar types of actions:

current_user.admin? || product.sold_by?(current_user)

How might we say this otherwise? How about:

product.can_administer?(current_user)

Or we could possibly use a permissions gem like CanCan.

What are you doing to simplify your views?

What other techniques are useful to make your code more readable, and more easy to work with by designers? Let us know!

Text

As your Ruby/Rails codebase grows, it’s important to take note of patterns that are or are not working. As we move into 2014 here at Reverb, with a year of experience in building and maintaining a large marketplace at breakneck velocity, here are our learnings.

These tips assume you are growing a sizeable Rails codebase with a domain layer living outside of Rails. If you need help getting started on that, I highly recommend these resources for building domain driven applications.

Service objects with many responsibilities

Avoid naming your PORO classes NounService such as UserService, ProductService, etc. These invite large growing classes with many responsibilities, instead use Use Case classes that do only one thing. For example, Reverb::Accounts::ForgotPassword, or Reverb::Orders::FinalizeCheckout. On a related note, find methods that are used in only one use case and move them there. Don’t bloat your ActiveRecord models with methods that are specific to a Use Case, instead create POROs to break Use Cases into simpler parts.

Un-namespaced classes in the domain layer

Our domain layer, living in app/reverb now has more than 236 classes. It would be a nightmare if they were all in one flat directory, yet that’s how they started. These days, we group things by responsibilities such as app/reverb/checkout and app/reverb/offers. As with service class naming, we try to keep namespaces based on domain concepts such as checkout rather than the Railsy/Nouny approach of naming things after models.

Including modules to share functionality

We believe that sharing code via mixins is largely a smell. It definitely has its uses, but it should not be reached for as an everyday pattern. The reason is it makes it very difficult to find where your methods are coming from and to cleanly read a class definition and see its public API. Mixins with public methods increase surface area of your objects, leading to further coupling in the users of your object. Mixins may be appropriate in cases where they are the only way to extend an object, such as is the case often times with ActiveRecord. Instead of mixins, delegate to collaborator objects explicitly.

Any kind of dynamic method invocation

Sends, especially with interpolated method names are impossible to grep for and refactor. Think thrice before doing this. Likewise, we are proud to say that in approximately 25k lines of application code, we have zero usages of method_missing. In my past experience, using this technique only invites headache for maintenance, and is only appropriate when crafting very tightly specified DSLs, that are usually best left to external gems.

Learn how we enforce this in our codebase with a failing spec.

Rails Helpers

Do Not Use. Rails helpers create globally accessible methods. There are valid uses but they should be limited to customizing the framework itself. A good example is something like button_to which enhances link_to with specific button css classes. A bad example would be anything domain specific like link_to_user. Instead move methods into decorators. We use Draper, but any type of delegator may be used to implement decorators.

Do you agree with these approaches? We’d love to hear from you. Also, we’re hiring. If you’re a software developer with a passion for product ownership, small teams, lean startups, and are a musician/gearhead, Reverb.com is literally your dream job. Find out more on our jobs page.

Text

Recently, we got into writing some of our first RSpec custom matchers. The API for creating them is actually quite straightforward, and there are some nice wins in expressiveness and the kinds of things you can test once you start using them. Here are three current use cases.

Using matchers to for duck-typed message expectations on attributes

Here’s an example of a fast spec that’s decoupled from Rails. In this case, we’re testing some contest subscription logic. We want to ensure that the contest is going to be passed a User that has an email address. But actually we don’t care that it’s a User model or some other thing, as long as it has an email. Defining a custom matcher allows us to assert against the email without having to require the User class in our tests:

https://gist.github.com/7226933

A custom matcher to deal with random or uncertain test data that should match a format

Here’s a test that deals with dates from our Auction service integration endpoint. This is a VCR spec that hits a remote service. This service returns a specific date that gets recorded in the VCR cassette files. Rather than hardcoding that date into the test and dealing with brittle tests when the spec has to be re-recorded, we’ll just assert on the format of the date:

https://gist.github.com/7226943

A custom matcher to test ActiveRelation scopes

We always weigh the cost of testing against the likelihood of breakage. In the case of scopes, they’re often quite trivial and we end up testing the ActiveRecord API more than anything. The cost to actually test them requires loading enough data into the database to indicate that the filters are working, which can be quite expensive depending on the object graph. Because of this, we can simply assert that the scope is doing what we think it’s doing:

https://gist.github.com/7226954

Text

Here are some of our favorite books, articles, and talks that inform how we like to write code at Reverb.com. If you like these resources, maybe you’d like to join us? We’re hiring.

Practical Object Oriented Design in Ruby - Sandi Metz
A great guide for both beginners and intermediate programmers that really helps you think about SOLID design principles.

Objects on Rails - Avdi Grimm
One of my favorites, this book contains many thought experiments represented in code. What if the ActiveRecord API was made private and you used it truly as a data abstraction layer and nothing more? Food for thought that will make you write better code.

Clean Ruby - Jim Gay
Another book that makes you think - while some of the code examples are pretty different than what you find in vanilla Rails apps, this gives you some ideas for how you could write loosely coupled code using the ideas of Roles and Contexts.

Growing Object Oriented Software, Guided by Tests
A classic affectionately known as GOOS - the examples are in Java but very relevant to what we’re going through in Ruby land these days.

Clean Code Handbook - Uncle Bob Martin
Again, not Ruby specific, but lots of good basic code hygiene ideas that will keep your code smelling and feeling fresh even when it’s had a hard day.

Keynote: Architecture the Lost Years - “Uncle Bob” Martin
The granddaddy of architecture talks - I love this because it totally changed my perspective on writing code from being Noun/Resource oriented to reifying some of the complex Verbs that happen in larger systems. The result is simpler to understand classes that are easy to reason about.

Hexagonal Rails - Matt Wynne
Takes some of Uncle Bob’s ideas about decoupling and applies them to Rails. Some of this code will seem foreign coming from vanilla Rails approaches, and it doesn’t become apparent that it is useful until you’re knee deep in a larger project. But give it a chance, it actually helps a lot to decouple yourself a bit.

Fast Rails Tests - Corey Haines
If you’re still firing up your Rails to run tests, this talk will set you straight. 

Why you don’t get mock objects
A great talk that goes hand in hand with the GOOS book. Talks about when you would use mocks vs stubs, what the difference is, and why you should care. A very clear and concise delivery that might clean up your testing approach.

7 patterns to refactor fat ActiveRecord models
One of my all time favorite articles that encompasses many different object oriented patterns. It’s actually less about ActiveRecord than its title might entail. The reason it even mentions AR is that most people stuff the majority of their logic into ActiveRecord models. Even if that doesn’t sound like you, this article provides many ideas from View Models to Service and Policy objects. 

Bonus!

Gary Bernhardt - Boundaries
Probably my favorite of Gary’s work. Very information dense and worth pausing every few minutes and really digesting. I’ve often intuitively refactored code into functional and imperative pieces but this talk really clarifies how you go about seeing those patterns and separating your APIs so that their boundaries are simple and easy to test.

blog comments powered by Disqus
Crafted in Chicago