How to Use Searchkick and ElasticSearch in Your Rails App For Complex Search Indexing

For reasons that elude me, I have always been obsessed with “speedcoding.” That is, I like to see how fast I can implement a very large feature in a ridiculously short amount of time. I won’t lie: this kind of trait goes hand-in-hand with phrases like “cowboy coding” and “Balmer peak,” and with age, I’ve largely outgrown it, but the mood still hits me every now and then.

I recently enjoyed one of these moments while toying around with some code for Treehouse, for the fun of it.

imageedit_5_3400066282

In a past life, I spent about a year working on a team for DeviantArt whose sole purpose was to improve search results on the site. If you were not aware, DeviantArt’s search is done entirely in-house by people who have PhDs in math. They’re brilliant people who will talk your ears off about facets, scoring, histograms, and tagging metadata. I didn’t work on any of the search indexing services myself (which were all written in C++), but I was heavily exposed to the bits of it that were included in the main app, written in PHP. And as a result of that, I know more about search indexing than I’d like to say I know.

CloudSearch or Ransack?

So, seeing poorly implemented search indexing tools also causes me mental anguish. That’s how I feel about Amazon CloudSearch, in general, which is a tool Treehouse has used for one of its most major site features. It’s not the worst indexing tool in the world but I really dislike that you have to hit your indices through an API since it’s all hosted externally, which seems unnecessary, unlike hitting a CDN for assets. That’s like hosting your Redis stores on a third-party service: why. But, worse, for a few internal tools, Treehouse uses a Rails gem called Ransack.

I don’t mind Ransack. It has its heart in the right place, but it leverages ActiveRecord for its querying and so, you’ll have to put a lot of effort into optimizing indices on your database tables if you expect it to work even halfway decently as the size of the table you’re querying grows. This also assumes you’re not doing expensive table joins as part of your query.

Searchkick to the Rescue

I recently decided to see what would happen if I used ElasticSearch for a fairly complex search, using a gem called Searchkick. I really like Searchkick because out-of-the-box, there’s no configuration needed. If you want to index your User model, it’s as simple as adding the gem to your Gemfile and a searchkick directive to the class:

And then reindexing the model:

The cool thing here is that you can also do your reindexing asynchronously so that it won’t block processes or have a dramatic impact on your application’s performance.

You can then search all attributes of User (i.e. name, e-mail, city) like so:

And you’ll find plenty of demos and tutorials for that all over the place, but who ever needs the simplest use case?

I had a few different needs:

1. Because Searchkick uses ElasticSearch, you can’t chain scopes off of the model prior to running the search like so:

I mean, you can, but — it’ll ignore the named scope and still run your search against all User records. So I needed to be able to account for different scopes, and the above piece of code simply does not work and cannot be made to work.

2. I needed to be able to sort my results by a variety of things which weren’t necessarily attributes on the model itself. For example: I needed to sort by the time difference between the model’s created_at attribute and its updated_at attribute. Or I needed to sort by the created_at timestamp on a child association. ElasticSearch’s DSL supports a sort order constraint, but how do you sort by a value that isn’t indexed with the model?

3. As I started to index more things, I noticed my controller logic was growing wily. I needed some sort of presenter type class or simply a PORO to organize my Searchkick search.

So I’m going to walk through how I developed this search feature, stopping to explain my thought process along the way. Because I didn’t feel like getting sued by my employer for any potential intellectual property theft, I’ve used a completely different search feature that has absolutely nothing to do with what I was originally building a search for.

Once I was finished writing this code, I was able to roll out a second sortable, filterable, search tool for another model in about 20 minutes reusing the same pattern.

Where I Started

I wanted to index a model called Movie. Each Movie is directed by a Director and has many Actors through a relational model called ActorRole.

Searchkick allows you to override which columns are used in searches via a method called search_data. My first step is to find out what things I need to index here!

What this does is allow me to continue indexing the attributes on the model itself, but also includes a couple of other pieces of denormalized data from associations, namely the name of the Director who directed the Movie and the names of anyone who acted in the movie, both pieces of data that are not stored on the Movie record.

So, assuming that I have a Movie with the title “The Room” directed by esteemed actor, director, and writer Tommy Wiseau, I can now search for “Tommy Wiseau” and “The Room” will be one of my search results–both because he acted in the movie and directed it.

If you’re used to working with relational databases, seeing denormalized data stored this way might bother you, but it shouldn’t. Remember, the purpose of these indices is for aiding in searching, not for data management. Your indices do not need to look pretty–they need to simply be a collection of values that you search with, mapped to their respective data types. That’s why it’s a separate data store from your primary database, afterall.

You should always reindex after making changes to the search attributes, so that ElasticSearch can pick up anything new.

Implementing This In A Controller

As you can see, the search method, provided by Searchkick, takes 2 parameters. The first is a query string. The second is an options hash. Already, I’m passing two options to set up pagination support. You might imagine how hairy this will start to get once I need to do more complex search functionality.

I’d like to move this logic into its own service object for a couple of reasons:

1. I’m a big fan of keeping controller actions skinny (as most Sandi Metz fans are)
2. If I later decide to add additional searches, I am likely going to reuse this logic.

So let’s do that.

I still don’t like this though. It’s not generic enough, and we’ll see why in a minute as we continue to build it out. I prefer to get something working before trying to refactor it.

Extra Beef – Filtering

I don’t know about you, but I’ve never been to a movie site that didn’t offer browsing by genre. That’s just an obvious thing about movies, yeah? So we need to work that into our search somehow. The problem is, since we’re using ElasticSearch, we can’t do any initial filtering through ActiveRecord scoping. Everything needs to take place within the Searchkick options. So we need to consider that in our search class.

The options hash is now starting to get polluted and messy, which means it’s probably time to extract parts of it out into its own method:

These are simple use cases. But what if you wanted to filter on something a bit less obvious that doesn’t necessarily seem like it would be a search keyword–like say, filtering Movie based on whether the director is still alive or has died before a certain date. Sure, that’s not a common thing to filter on, but a majority of our lives as developers are building out logic that has some special meaning to our product or customer, otherwise we’d all be using pre-existing open source software and calling it a day.

To do this, I need to add that denormalized data to the search index.

When you reindex your model, Searchkick will pick up that you’re indexing a date and you’ll be able to evaluate it as such in your search:

lte and gte are both parts of the ElasticSearch DSL, if you were curious. And honestly, I think it’d be weird if someone had a future death date listed but, again, we’re just toying with data here 😉 You could even filter within a range if you had two date objects, using both lte and gte.

I could continue adding ways to filter on additional attributes, but it’s largely rinse and repeat from here, with some mild Ruby refactoring along the way.

Sorting

This was the one part that gave me pause, but it’s not wildly different from filtering via where. Say I present Movie results in a table that contains columns for its title, genre, release year, and director’s birth year. The first three items are simple to sort on because they’re already indexed attributes. Just like we had to add the director’s death date for filtering on that, we’ll need to add the director’s birth year in order to provide sorting options for that:

And add a sorting option to our search call:

Pretty simple. One thing I want to point out here is that ElasticSearch allows you to sort by _score. You can sort by multiple attributes, so you might want to consider continuing to sort by score, because that’s one of the niftier things about Elasticsearch–as it receives more queries and its indices grow, it grows more intelligent about which results are relevant, and sorting by score will weight the more relevant results towards the top.

Moving on! Now, our MovieSearch class, in full, looks like this:

Refactoring

And this is where we can start to think about refactoring potential. Some of the logic in this class is tightly coupled to the Movie class, but some of it is generic enough that it could be used for any model using Searchkick for searching. So maybe it’s time that we break this into a base class which our MovieSearch class can inherit from:

I added a new method called search_class that raises a “Not Implemented” error on the base class. If the child class fails to implement that, as it should since it specifies which model to search, that error will be raised. Because we were able to extract so much into the base class, the MovieSearch only had to include the search_class method and a where method for movie-specific filtering logic. You could potentially override the order method as well if you wanted to have a default sort order, like say, if you were filtering by the director’s death date, you always wanted to make sure you sorted results by that attribute in descending order.

Final Thoughts

Cache-busting

There’s a lot more you could do here. I just wanted to dig in a little bit beneath the surface of all the tutorials that choose to cover the most basic use case. One thing, I’d like to point out though is that when you use ElasticSearch on a model that has child associations in its search data, you’ll need to make sure that the parent model gets reindexed when the child object gets altered. Searchkick automatically reindexes when the model itself changes, so just as you would handle cache-busting, you need to make sure your associations have a touch: true directive to trigger this reindexing!

One of my coworkers, Amos, also shared with me an interesting, alternative approach to handling these kinds of issues by adding instrumentation to the child model’s lifecycle that notifies when it needs to be reindexed and then subscribing to those notifications to ensure that a reindex takes place. I really like this approach too and would heavily advocate it if your searches start to get heavily burdened by ActiveRecord associations.

“I hate service objects and think aspect-oriented programming is the way of the future!”

That’s fine and I understand there’s a couple of different ways you could propose to architect the code I wrote here. Instead of building a service object, you could make a Searchable aspects module that is included in your model and override the where and order methods within your model instead of building separate search classes. On one hand, I’m not a gigantic fan of this because it places logic that doesn’t belong on the model in the model. On the other hand, if you look at how Searchkick works, it’s already doing this by forcing you to override its search_data method on the model. In short: ¯\_(ツ)_/¯

Code Climate and Flog

True story: Flog will hate you if you have even the slightest bit of complexity in your search_data methods and if you choose to extract out relational data into their own methods in cases where you were needing to pass blocks to map, you’ll start to get that stinky feeling that you’re violating the Law of Demeter. So, in a way, I feel like having search_data on the model is a code smell that Searchkick forces you to commit, but, to reiterate: ¯\_(ツ)_/¯

“I love you for writing this but I know something you don’t know and want to contribute!” /
“I love you for writing this but I’m a hands-on learner and want to download the code to play with myself!”

Did you find this article useful but want to have a more hands-on learning experience? Good news! I’ve put this code on Github where you can clone it and play with it on your own.

1Q84 – Books 1 and 2

I’m currently 700 pages into the 1159-page Haruki Murakami novel 1Q84. Here are the thoughts I’ve collected, spoilers and all, in no particular order thus far.

There be spoilers below. 

  • What if the novel that Tengo is working on after Air Chrysalis is actually the novel I am reading, 1Q84? What if Aomame has been written into the novel? After all, the foundation of the book is based on 1984, where history is rewritten. Perhaps Tengo is in a future where the past is forgotten and he is rewriting history, reminiscing of a childhood love he never saw again.
  • I really appreciate that Tengo has forgotten his girlfriend’s name. I feel like so much of life is repetitive events with people we know without really knowing. And it’s not that you don’t care about these people, but just that in going through the motions, you forget to get to know them further.
  • I don’t know if it’s just me but I had no idea what the Willow House was supposed to be for the first two chapters of Aomame’s story that mentioned it.
  • I can’t not picture the Dowager as an American southern aristocrat with Cruella Deville hair.
  • In that same respect, I also can’t not picture The Professor as a Japanese version of Edward James Olmos. I have no idea why.
  • They keep quoting lyrics from Frank Sinatra’s “It’s Only a Paper Moon.” Given the two moons in the story, what does it mean? In the song, love isn’t real without that other person–it’s a fairytale. Is 1Q84 a fairytale as well until Aomame or Tengo remember they’re in love and then suddenly become a part of it?
  • Janacek’s Sinfonietta is such an odd choice of a song to have recur throughout a book. The intro fanfare is so cacophonous and discordant. It’s a war theme.
  • There’s a lot to make me think a primary theme of this novel is feminism. So much sexual abuse and vengeance in the name of sexual abuse. Aomame doesn’t want a lover. Ayumi doesn’t have time for a lover.
  • Speaking of which, Aomame’s revenge on her dead best friend’s husband? I can’t think of anything more annoying than literally having to replace every. single. item in my house. That is some skilled shit.
  • I love the way Murakami describes the first appearance of Ushikawa:
    • “…some creepy thing that had crawled out of a hole in the earth — a slimy thing of uncertain shape that in fact was not supposed to come out in to the light.”
    • “…black, curly hair that had been allowed to grow too long, hanging down shaggily over the man’s ears. Ninety-eight people out of a hundred would probably be reminded by it of pubic hair. Tengo had no idea what the other two would think.”
    • “It was not just that he had terrible style: he also gave the impression that he was deliberately desecrating the very idea of wearing clothes.”
  • Tengo’s girlfriend’s dream about the cottage in the woods really freaks me out. She says she has a sense of dread about why the food was left at the table, why after hours, it’s still steaming hot, why it’s getting dark and whoever left it is still not back, as if they abandoned it to run away from a monster. And Tengo suggests that she is the monster and she gets offended. But what really freaks me out about that is just the continuity of the scene. All alone with the forever-steaming food. Isn’t that what hell is? Being stuck forever with dread?
  • Book 2 is really boring and drawn out. I feel like he was trying to be really dramatic in spending 8 pages describing a handgun and how it’s handled, but the deep impact of that really falls short. Yes, guns are kind of more heavy than they look. Yes, they’re made of metal. Yes, they’re powerful and you have to be extremely safe with them. I get it. I did appreciate the Chekhov reference that once a gun appears in a story, it has to be used. I feel like, at this point, I don’t really care if the gun gets used or not, though. Murakami makes it really hard to care about Aomame given that she’s not a very emotional person.
  • I have really appreciated how blunt Aomame is though about her sexuality, from her telling a guy in a bar that she likes big cocks down to her weird sensation the morning after of her asshole having been stretched open from anal sex. It’s a little bit shocking, from someone who presents herself so properly in all other venues of her life.
  • The Little People make me think of The Lilliputians in Gulliver’s Travels. I can’t really figure out what their angle is though. I know they’re not good, but I don’t know that they’re bad either. They’re just… chaotic supernatural forces, as far as I can tell, that are tied to events that do seem bad–child molestation, disappearances, cults, exploding dogs?
  • Fuka Eri asking what Tengo what “real” meant was interesting given her character’s whole existential crisis in Air Chrysalis upon learning she had this dohta clone.
  • Murakami is obsessed with breasts. I know more about Fuka Eri’s breasts than her face.
  • I don’t know what to feel about the whole concept of the maza and the dohta. Is Fuka Eri being separated from her dohta (the shadow of her heart and mind) the reason she is perceived as dyslexic or is she actually dyslexic anyway?
  • What are the criteria for being chosen as the Perceiver and Receiver? Is it just a coincidence that the Leader and his daughter (or her dohta?) are both? What happens if the Perceiver and Receiver don’t know one another? Do the Little People have to orchestrate that whole shebang? Are they a global force or just a Japanese thing?
  • I feel like there is a bigger conspiracy laying ahead. The first time that Tengo got a call from Fuka Eri when she was in hiding, he could hear children in the background. I feel like she was staying in the same condo that Aomame is staying in after killing the Leader. Which I think means that two opposing forces are actually working together (possibly the Dowager knows the Professor? Or… the Dowager’s long lost son is the Leader) Who knows.
  • I really hope this book wraps up in a way that doesn’t just feel like the whole thing was a homage to Orwell’s 1984, because I’d be really disappointed with that. I just think Murakami can rise to the occasion to not need to use another literary work as a plot crutch, especially for his longest work yet.

You Can’t Live On In Anger / 7 Months After Miscarrying

31 weeks ago, on Father’s Day 2015, I rode my bike to CVS. For two weeks, I’d had a really obnoxious cramp in my lower abdomen. I thought I had an ovarian cyst because it was sharp and stabby. But the doctor didn’t find anything wrong and sent me home.

I made the trip to CVS every couple of weeks usually, to purchase a home pregnancy test. It was just a formality for me, to the point that when I took the test, I typically just set it aside and would glance at it later in confirmation that things were normal. Normal for me, anyway.

But this time, before I could even fully lift the test back up, something was off. It was positive. Extremely positive. And like most people with an unplanned pregnancy, I started to pace around frantically, trying to catch my breath, before calling my boyfriend. Then I took another test. And another. A real Hollywood cliche, but it’s grounded in so much reality.

We walked around the neighborhood like zombies for an hour. It felt like a nightmare. Not because I hate children or because I don’t love Joel. My brain just couldn’t comprehend the amount of responsibility.

The baby changed things. It changed me. It changed my relationship. And it grew. And as it grew, I grew inside. I bonded with it. I ate a lot of kale suddenly. I sang songs like “Hey Jude” to it even though I know fetuses that small can’t hear. Some days, I felt like a whole bright world awaited me. Other days, it felt like it was just me and baby versus the world.

Then I found out that one baby was actually two. And I felt disconnected again. I felt ashamed for feeling disconnected. It’s hard feeling like you spent time bonding with one person only to find out that all along, you were actually bonding with two people. It felt weird knowing there was another member audience to my singing. It felt weird knowing the different foods I craved… that maybe each one was triggered by a different baby.

And when the doctor said the words, “high risk,” it terrified me. Then came abdominal pain I’ve never felt before. Pain I’m sure is not even half as bad as labor pain, that caused me to double over, lose my breath, and not be able to stand. And the babies were gone.

I had to take a week off of my job to recover from the loss. I didn’t know back then what all that sedentary navel-gazing would do to me. Like the twins changed me, their loss changed me. And my reaction to the loss was nothing like my boyfriend’s reaction to the loss. And that changed the dynamic between us as well. Seeing happy families made me cry. Hearing people complain about their young children annoyed me because I felt like they had lost sight of what they had. I felt lost.

And worse, I felt no finality. When you are pregnant, you get a due date. My original due date was February 23, 2016. Because they were twins, the due date was actually more like around 36 weeks, since twins are typically born premature, so January 23, 2016. But twins vary greatly in when they decide to come. Anywhere from 32 weeks to a normal full-term. It was impossible to have the feeling of “this is when they’d have been born. I can let go.”

Shortly after I found out I was pregnant, I began a cross-stitch piece, not knowing how epic it would be, of the Overworld map of World 1 in Super Mario Brothers 3. After the loss, I continued. Somewhere around November, I knew, even though I was nowhere near finished with it, that whenever I finished this map is when they would have been born. It was a pregnancy-length piece.

And sure enough, I finished it on January 24, 2016, 1 day past 36 weeks. And not that the piece dictated where my grief ended, but I looked up from the piece and realized I’m in a better place now than I was before.

For months, I was angry. I thought my grief would be channeled through sadness. Instead it came through in anger. I was angry at everything in my life. I was angry with Joel. I was angry with where I was living. I was angry with my job. I was angry with myself. Nothing could make me happy because I wasn’t even willing to give it the chance to do so. I was defensively preventing myself from moving forward with my life.

And then, through some magic grace in the universe, a calm surged up and embraced me. And I was able to breathe again. I still get angry. But I’m a little less so now.

And strangely, the map from start to finish… it works. There were a lot of hills. And hammer brothers. And invincibility stars. And mushrooms. And Koopas. And magic flutes. And three lives at the very start. And I lost a couple along the way, but I somehow made it to the end of World 1.

IMG_0366

“Woman in a Meeting” Speak And Its Role In Software Development

Last week, I came across an article on Buzzfeed, a news source that I don’t really count as a news source, on the subject of “Woman in a Meeting” speak. It was all about the idea of women sugar-coating their opinions in business settings out of concern that they will come across as brash or bitchy. That article, of course, stemmed from a Washington Post article in which famous historical quotes were re-imagined as if they were spoken by women in business meetings.

The topic hit very close to home for me. Not because I am guilty of it–in fact, if I look through my most recent exchanges with others, I am fairly strong-willed and blunt in how I share my opinions with others. I occasionally use emojis. I occasionally say “haha” when it’s appropriate because I like for people to know I’m not a robot.

However, I stand by the points I make generally and don’t make excuses for them.  Why? Because a fairly large part of my job is providing critical feedback to others. I simply can’t afford to hem and haw on my opinions, because people rely on me to know what I’m talking about. This isn’t me being arrogant. Being cutesy about it would only give others pause about my ability to provide assistance, so it has no place in my exchanges with others.

But I didn’t always speak bluntly. It’s a strength I passively developed as I grew as a software developer and I think it’s really important that you develop good communication habits early in your career that allow you to continue building that voice! Occasionally, I see this speech pattern in others and it has little to do with gender identity. Examining it as such is using it as a crutch, I think.  Having an opinion and being able to state it so it’s heard is like singing. It doesn’t matter how eloquent or beautiful it is if no one can hear it. Having a voice is about having strength but also balancing that strength so that there’s still melody and you don’t sound like you’re yelling. So here are some thoughts on building that trait.

Don’t Apologize for Your Weakness

“I’m sorry” has one place in your interactions with your peers and that’s in expressing sincere remorse.

Times it is okay to say “I’m sorry” as a software developer:

  • You force pushed commits to master.
  • It’s been 2 days and you forgot to review someone’s code.
  • You insulted someone. Or their family. Or their beliefs. Or something deeply personal.
  • You have severely inconvenienced someone (in a way that is obvious to you)
  • You overcommitted yourself and failed to hold to your commitments in a way that caused problems for someone else’s workflow.

Here’s times you shouldn’t apologize:

  • You don’t know something
  • You don’t feel confident about your opinions.
  • You have an opinion that conflicts with someone else’s opinion.

Also, don’t confuse apologies with gratitude. Suppose someone took time out of their day to explain how something works to you. Don’t say, “I’m sorry for eating up your time.” Say, “Thank you for taking the time to explain this to me. It’s going to be useful when [whatever it’s going to be useful for in the future]!”

Remember, when you apologize unnecessarily, you are diluting the meaning of sincere apologies and you are only adding filler and fluff to a meaningful conversation.

Find Your Strengths

Your soft skills as a developer are just as valuable as your hard skills. These are skills you’ve been working on since you were a child. They are part of your personality. Just like you walked into your 2nd grade classroom not knowing the difference between sedimentary and igneous rocks, you’ll walk into your first job as a software developer with not a lot of knowledge to show off that you’ll soon learn. People’s willingness to engage with you when you know nothing will be built entirely on the kind of personality you have.

Don’t Acknowledge Your Weaknesses to Deflect Your Strengths

Things you might be tempted to say:

  • “You probably know more about this than me”
  • “I’m not an expert”
  • “I’m probably wrong but…”
  • “Just a thought.”
  • “This is just my opinion but…”
  • “I don’t know if this will make sense but…”

These are implicitly understood things. You might say them because you’re afraid if you are wrong, that you’ll look dumb. But they’re not necessary. Regardless of whether you’re an actual expert or not, the person you’re speaking with now has your opinion to decide whether they agree with it or not. And they know it’s your opinion. Or your thought. And really, it doesn’t matter who knows more about what. Because sometimes someone who has expert knowledge of something has a moment of stupidity just like someone who might know very little about the intricacies of a system might have a genius observation.

You Can Express Your Uncertainty Without Putting Yourself (or Others) Down

Here are some great ways to make it clear to your colleagues that you have an opinion, think it might have some worth, but need some additional feedback or assistance:

  • “I’d be interested to hear your thoughts too on this!”
  • “Let’s chat about how we can actually implement this idea I have.”
  • “Can you be a rubber duck and listen to some ideas I have?”
  • “I know you know a lot about this thing I’m working on so I’d really appreciate your feedback!”
  • “I like your ideas but I have some thoughts too that I think would work well here.”

The list of possible ways to express this goes on and can be amended to whatever context is necessary. The idea here is that if you want to establish your voice, stand by your opinions and show others that you are grateful for their opinions too.

You Can “Haha” and Emoji and Cat GIF it Up All You Want

I don’t know why people think these things take away credibility. The people I work with that I like the most know when it’s appropriate to laugh, know that not everything is a personal attack, and have fun doing what they do. The best way to reflect your credibility is by showing others that you like your career and that you feel in your own skin doing it. Don’t stop laughing. Because laughter is part of your voice too just as much as your words are.

tumblr_nhig62jVE51sn75h6o1_400

You’re Bad At Reviewing Code (Or Are You?)

Last month, I wrote a piece discussing the characteristics of poorly written and well written pull requests. And with that, I started to ponder the other side of the fence: How does one review code well?

Reviewing code can be frustrating, even when the pull request is well-written. Say you’ve been working on the same thing for 3 days now and suddenly you’re asked to review a pull request with a 35-file changeset which includes database migrations and makes significant architectural changes to the application. Big changeset or not, many PRs are very capable of taking down a site on deploy and it’s scary to find yourself responsible for that if you miss something.

You don’t want to take the site down

I’ve done that. If you’ve spent any time working as a professional developer, you probably have too. One time, shortly after I had joined Treehouse, I spent a day or two writing some new stats collection methods that were run as part of a daily rake task. The pull request was approved, my tests passed, the  build passed in our continuous integration service. And then I deployed it. And it took down Treehouse immediately. The culprit? Bad data.

Taking a site down means doing a post-mortem and trying to figure out, “What can we do to make sure this doesn’t happen again?” And that’s great. But it’d be greater if you didn’t land there in the first place.

FldBatL

Ask questions, even if you suspect they sound dumb

One thing that I heavily advocate in reviewing a pull request is letting go of your assumptions about how things work and approaching the code as if you had no awareness of the application’s nuances. As you come across these nuances, first run an internal monologue and explain to yourself how those things work. If you can’t find a way to explain it to yourself in clear, easy to understand language, it’s fair game for leaving a comment on the merit that other developers who aren’t as experienced with the application won’t intuitively understand it.

This might sound like it’s time-consuming, but once you’ve adapted this philosophy for a brief time, it’ll become quick to you, much like speaking a foreign language is with practice.

CO2oB11

But don’t be afraid to approve.

You don’t have to be a pedantic asshole while reviewing code. I know, you have this voice in your subconscious that worries, “Will they even believe I reviewed their code if I just give it the old thumbs up without any additional comments?” Sometimes someone will really just knock it out of the park, though. It happens. You don’t have to be pedantic for the sake of fostering credibility. I swear.

anigif_enhanced-buzz-18929-1420303977-4

“It’ll only be like this for a little while… I promise…”

I’m guilty of this occasionally. It happens a lot when you work on large, moving-target type projects. There’s a compromise between understanding deadlines and understanding that you’re introducing future technical debt to an application. If you work on public-facing products, this can happen a lot.

When you see something in a pull request that looks sketchy, hackish, or like a shortcut, and the author of the code is excusing it with time constraints due to a deadline, it’s appropriate to question the timeline for remedying the workaround or at least prompting a discussion of: what the long-term plan for that workaround is, and making sure that it is documented somewhere so that it doesn’t get left behind as painful legacy code to clean up for some new developer 3 years down the road. If you ever see #TODO: Fix this in a pull request, a discussion should be happening surrounding that.

Mind you, this conversation should not be done in a finger-pointing manner. It should be done constructively, with the primary concern being the health of the codebase you’re maintaining. But also empathetically, with the understanding that one day, you too will be on the opposite side of the table.

anigif_enhanced-1848-1411417802-5

Share knowledge if you have it

Reviewing a pull request is not just a matter of “does this work?” It’s a matter of “does this work in the most effective and efficient way?” If you know of a way to more cleanly write something and you fail to point it out to the author, you’re doing a disservice to them, intellectually, and future code that they write. This happens a lot when working with Rails apps, because there are so many useful things available through ActiveSupport that even the most seasoned developers might not know about.

anigif_enhanced-3376-1414921505-1

It works, but does it work well?

Just because you tested something in your local development environment and confirmed that it works doesn’t necessarily mean it’s good to ship into a production environment. Performance should be a concern as well. Can you benchmark changes made? Do you have access to New Relic or other tools locally? If you suspect that there may be potential performance issues with a pull request, you should be checking these things.

anigif_enhanced-5488-1416337355-5

Does it scale?

What works now may not work well forever or even next month. Don’t think of the pull request in isolation. Think about how it will gel and coalesce with other parts of your codebase. If you have 500 users today, how do you think this code will fare when you have 5,000 or 50,000? Are there logical constraints to the code being committed that will make working in future product features difficult or annoyingly complex?  Does this addition to your codebase put it one step closer to being a monolithic piece of crap? Would it serve you better as a micro service?

Having these conversations sooner than later will save you headaches in the future. You don’t have to over-engineer. But you do have to at least consider the implications of not over-engineering.

anigif_enhanced-5723-1415662903-7

Is there something else that will do this better?

This is awkward. Someone has just written a large pull request but you know of a very simple gem or library that does exactly what they just labored over, only the gem/library you know of does it… better or more thoroughly.  Do you say something? You should. You should also leave that decision in their hands of what they want to do with that information, awkward as it is.

anigif_enhanced-16693-1414497983-4

Remember, your coworkers are humans too.

When I review a large pull request, I compliment just as much as a I critique. Even if it’s just a “thank you for doing this.” People need positive feedback. They need to be reminded every now and then that there’s a reason they’re doing what they’re doing. As cold and robotic as code can be, it’s on us as developers to high five and shower each other with animated GIFs and creepy smiling cat face emojis.

Remember, one day, you’ll be having the worst day in the world and someone will comment on a line of your PR with, “woah that’s an awesome idea, :clap:” and you’ll swell with pride and happiness. Remember that every time you say something nice, someone else might be living that same moment.

tumblr_ntlritqDmM1sn75h6o1_400

Your Pull Request Sucks (or does it?)

One of the things that slows me down the most as a developer is getting roadblocked on a pull request. I can spend a frivolous amount of time, say 15 minutes, actually producing and testing my changes and then on rare occasion be stuck waiting hours or days for it to be reviewed.

There’s only so much you can do to alter another person’s availability to review your code, but what hit me over time is that other developers are like me: they switch contexts just as much as they switch git branches. People need context! Unfortunately, reading a diff is not a fantastic way to establish context and can take just as much time as it takes to review the PR itself. And not having context can cause people to procrastinate or simply forget to review your pull request until you bug them to do so.

I  have alway written pull requests like any other developer might. I explained what the changes were, relative to nothing else. The title of the pull request would be well-written and explain the ultimate goal of the changes made and because of that, I assumed that the changes would be implicitly understood by the reviewer.

Alas, other developers do not necessarily work on the same area of the application as I do. Or have not recently worked on it. Or may misunderstand the human factor of what the changes are trying to achieve.  As someone who has been looking at the code for maybe days, I want to say, “That’s so obvious, do I really need to explain it?”

The answer to that is: “Maybe not, but what does it hurt to do so?” Who knows, maybe in 2 weeks, you’ll need to revisit this pull request. Maybe in 2 months a bug will be discovered that is the result of your changes and other people will get involved. Either way, there is no harm in transparency.

I’ll use examples of pull requests I have done to break down some ideas on what makes for bad, okay, and good pull requests. I feel no shame in this because I’ve learned from it! I work with several people who have produced awesome pull requests that were constructed in ways I found impressive, but putting other people’s work on display is weird and not cool, so this is sticking strictly to stuff I’ve done to highlight things.

What a Crappy Pull Request Looks Like

This is a pull request I did within my first month of working for Treehouse:

Screen Shot 2015-09-24 at 2.29.28 PM

Here’s why it sucks:

  1. What is “the right thing”?
  2. There’s mention of BugSnag, but no link to the actual error in BugSnag.
  3. “Make bugsnag stop crying” is very, very colloquial language. This is more of a nitpick on myself than anything, but if another developer were to look at this and speak English as a second language or not speak the same dialect of English as me, they might be ever-so-slightly confused by that description.
  4. No explanation of what I changed.
  5. Or why I changed it (other than to stop an error from occurring)

This pull request was almost certainly an emergency hotfix. In fact, I’m pretty sure it was me hotfixing someone else‘s code. Which, for all practical purposes, is the ideal situation for writing a very well-formed pull request (and tagging the responsible party!). It was a one-line change that adds a presence check to a variable. But a year and a half later, I don’t have any context for what this change was related to, which previous commit caused the issue I was fixing, or if there was even a GitHb issue logged for it. The pull request was reviewed and merged and probably was okay, but the title and description for it are horrid!

Reviewing a pull request should not make someone feel like they are solving a dramatic mystery.

tumblr_nuh1vgNaCo1qbzzgco1_1280

What an OK Pull Request Looks Like

Screen Shot 2015-09-24 at 2.37.33 PM

Here’s why it’s okay (but not necessarily good):

  • It references an issue (which is not always going to be available if you are building a feature or handling tech debt, but in this case, it’s applicable)
  • It humanely explains how a model works prior to the changes to give the reviewer a comparative understanding of what changes they are about to review. After all, not every developer intimately knows all the logical constraints of every class in the application they work on.
  • It explains why there is a problem with that model’s behavior both in terms of application logic and actual use case.
  • It proposes a solution in response to the problem explained.
  • It explains additional requirements related to the pull request (needing to run a job to fix data)
  • It acknowledges room for future improvements that might be outside of the scope of the pull request, in case those do come up in the discussion.

Here’s why it’s not good:

  • It doesn’t provide information on how it should be tested.
  • It doesn’t cover any concerns or additional implications that might be related to the changeset (in this pull request, I don’t really think there were any, but I think with a larger pull request that touches more classes, this might be a problem).
  • The language used in the title is okay, but it’s not completely clear. “point award” is referencing a model called “PointAward” and yet “vote” is actually referencing a model called “ForumVote.” For anyone that regularly looks at this code, they will likely immediately know what I’m talking about, but if someone new to the application were to look at this pull request, they might not know what a “point award” is (or if it’s a model even) or maybe they will go looking for a model called Vote and be absolutely confused when they don’t see anything named that.

A pull request should direct people to the appropriate parts of the application that are touched without confusion or having to ask for more information.

anigif_enhanced-buzz-4693-1416329884-4

What a Good Pull Request Looks Like

This is where things start to get more subjective. I’m using an example of a very large pull request I worked on a few months ago for this, in which I was maybe overly cautious about, but I think some the ideas surrounding it can be applicable to smaller pull requests as well. Is this pull request the best pull request in the history of the world? No, of course not. In fact, a few small-ish bugs emerged from it despite having a fair amount of clarity. The point is that it minimizes confusion about the intent of the pull request.

Screen Shot 2015-09-24 at 2.54.49 PMScreen Shot 2015-09-24 at 2.57.01 PMScreen Shot 2015-09-24 at 2.57.29 PM

Here’s why it’s good:

  • Its title expresses an objective and explains what mechanisms will be used to achieve it without being overly technical.
  • The description is well-formatted using Markdown so that it is readable to the reviewer. Obvious? Yeah, but when you’re conveying a lot of information, what looks reasonably readable to you can so easily look like a wall of text to an outsider.
  • It explains what the benefits of the changes are in a way that makes sense both from a technical and business perspective.
  • It breaks the changes down into a changelog.
  • It explains/defines jargon that may or may not be familiar to the reviewer.
  • It raises concerns in a way that prompts for feedback rather than dictating the direction the conversation contained within the pull request will go.
  • It appropriately tags people whose work is greatly affected by these changes or who may want to weigh in on the conversation.
  • It addresses issues that are possibly not within the scope of the pull request but have been observed while working on related library code.
  • It comprehensively covers all known [edge] cases for testing the changes.

Ways it could be better:

  • There is a lot of acronym usage in the description of the pull request. Sometimes that’s okay when it’s a concept that is more commonly communicated as an acronym than not (API) but turning something into an acronym that is not normally communicated that way out of laziness is potentially confusing (e.g. Active Merchant as “AM”).
  • Doesn’t really dig too deep into what underlying problem is being solved (“fraud” is mentioned, but certainly could have exposed more about how that was occurring historically)
  • Although it explains potential test cases, it doesn’t explain how to test those. Testing billing changes in a non-production environment is not always obvious to everyone because a payment processor’s development sandbox is behaviorally different and typically has its own test credit card numbers that you can use for producing successful transactions and declined transactions.
  • It could have explained the technicalities of the code being changed better, but in my case, this was intentional because I knew the person reviewing it was very, very familiar with the code changed.

One other thing that I like to do inside of pull requests is to spearhead conversations by making my own inline notes on code before the reviewer has the chance to do so, pointing out any areas that I am uncertain about that I am looking for suggestions on, adding additional clarity on why a particular line was changed if I think there may be even the slightest bit of confusion. That way the conversation in the pull request is bi-directional.

I like to think of writing pull requests like hosting an out-of-town guest. We have things in common, we speak the same language, we both have the same understanding of how human life works (we both know to breathe air and walk and other human things), but they don’t know all the intricacies of my town even if it might encompass some of the same things they’re familiar with from their own town or travels elsewhere. I talk like I assume they know some things but I’m not going to just jump in and say, “How about that Timbers game last week?” because I know they’ll have no idea of what I’m talking about–they are foreign to my town and they are potentially foreign to this code as well!

It’s common as a developer to think about learning from other developers from a strictly technical perspective: “Bob has more experience with this system than I do and can share information with me about it” or “Lisa is really good with CoffeeScript and might know of something that works better here…” but on a daily basis, every time you are interacting with other developers, you are subconsciously learning something about communication by trial and error. Any time you walk into a dead end with someone through miscommunication or find that something is useful to another person, that’s noteworthy and should impact how you verbalize things in the future! Don’t make people’s brains explode.

irCpBtzWVDIeI

I’d love to hear other developers’ thoughts, stories, and musings on how they set up pull requests and ways they’ve found room for improvement. Do you hate my principles? Do you love them? Do you have your own different standards? Comment below.

 

Disabling Superhero Mode at Night (or: How to Properly Turn off Work Notifications after Work)

Many developers suffer from Imposter Syndrome. I wrote an article about it. In fact, writing about Imposter Syndrome is, like, really trendy right now.

One of the common outcomes of Imposter Syndrome, however, which often goes undocumented, is the concept of “Superhero Mode.” This is a blanket term that I just made up to describe when a developer, often afflicted by Imposter Syndrome, over-exerts his or herself as a way of proving self-worth to others. Superhero Mode is kind of a misnomer because it implies arrogance, but the people suffering from it are often anything but arrogant–they’re often very humble, quiet, and soft-spoken.

And it’s not completely confined to people who suffer from IS, but the two often go hand in hand. A developer feels that if they work extra hard, harder than they’re used to, they will stand out and not be seen as a novice to a system that they are maybe fairly new to. It is sacrificing energy from one area of your life to create a gigantic pool of stamina to burn through on work-related tasks. This behavior starts early and becomes habit-forming, meaning that as you make adjustments in your career, you’ll continue down this road until you painfully burn out.

Unfortunately, the older that you get and the more responsibility you take on (both professional and personal), the sooner you will realize that Superhero Mode is not a scalable solution to professional credibility. First of all, you will become tired by it. Secondly, it will become part of your identity and an expectation others have of you, rather than a pleasant surprise when you exceed normal expectations. This isn’t anyone else’s fault. It is the most important thing you do for yourself: setting a standard of what you’re capable of doing and standing behind it. Maybe this will change as you grow wiser and more experienced, but whatever the case, it is something you have to create an answer for.

That said, if all employees are an instance of the Employee class, then Superhero Mode must be a privately scoped method on that class, never publicly accessible. And by that, I mean it has to be something you turn on yourself, not something others should be allowed to enable on you.

When Superhero Mode Beats The Crap Out of You

I recently spread myself too thin. I was getting angry a lot, but I didn’t really have anyone in particular to blame for it. I was getting migraines and my shoulders were thickly knotted all the time. I never felt relaxed. And I noticed I wasn’t getting enough exercise. And then I realized that it was because I never fully ended my work day. And it wasn’t helping me perform any better. In fact, I think it was making me more scatter-brained than ever.

I work remotely for Treehouse. We use HipChat to communicate. I start my work day sometime between 8 and 9 in the morning EST. And I end my work day between 5 and 6 in the evening EST. It started subtly. I was working through lunch. Then I wouldn’t close HipChat in the evening. I would leave it open. As long as I stayed on the computer, which I often use for personal reasons in the evening, I’d continue to get notifications any time someone messaged me or mentioned my name. Even if it was 10PM my time. I’d get sucked in and involved in whatever was going on and find myself working weird hours in addition to working a full day already.

I also would continue to get Github e-mail notifications in the evening or during my lunch. While walking to dinner with my boyfriend at 7PM one night, I felt my phone buzz and saw I had an e-mail related to a Github PR. I excused myself and then looked at it. Which is kind of rude. And I then got really annoyed. Of course, it could wait until the next morning, but when it’s thrusted at you, it’s really hard to ignore it. And because of that, the PR was in the back of my mind all evening and I couldn’t give my full attention to anything else.

I was so stressed out that I went to my manager about it. “I’m having a hard time. I want to be helpful and go above and beyond but I’m having a really hard time when it feels like I’m constantly reacting to everything” And his first response was, “You need to close HipChat at night.”

Being a Superhero By Destroying the Superhero

I took a series of directional changes in my day-to-day schedule and am happy to say that, so far, it works. To speak like an annoying meme, you have to give yourself time every day to “do you.” You will–eventually–have a nervous breakdown if you don’t. I’m fortunate that I recognized these issues before I got destroyed by them.

The biggest of these changes took some customization. I couldn’t figure out a way to turn off Github notifications that wasn’t an outright inconvenience. Turning on “Do Not Disturb” mode (or as I call it: “Crescent Moon Mode”) in iPhone was annoying because I wanted to get notifications for personal e-mail, text messages, incoming phone calls, social media, and other things. And my Github account linked to Treehouse is also my personal Github account, so all e-mails sent to it were going to my personal g-mail account, also very annoying.

Here is what I ultimately ended up doing. Which I don’t think is completely obvious:

  1. Github allows you to set up custom routing for e-mail notifications (link requires you to be logged in to Github)

Screen Shot 2015-09-21 at 2.22.26 PM

With this, I still get e-mail notifications for personal Github projects to my personal gmail account. But any activity that takes place in a repository owned by Treehouse now gets sent to my Treehouse e-mail account instead. This is a feature that I was not aware of until a few days ago and I wouldn’t be surprised if others were not aware of it either. Basecamp recently offered a way to automatically disable notifications between certain hours and I long for that same behavior in Github but until it exists, this works fine.

2. IMG_8842

I use the official Google Mail app. In the settings for secondary e-mail accounts, you can disable push notifications for anything except for e-mails flagged as “important.” I then set up a filter in my e-mail to ensure that arbitrary Github notifications never fall into this category. I continue to have my e-mail open on my computer (except after hours) so that these rules don’t affect that, but when I am out on the go, I no longer get random buzz-assaulted by a slew of comments on a PR.

3.  I close HipChat/online work chat. I was skeptical about this. Surely, there’s no difference between being flagged as “Do Not Disturb” and being offline, right? There is though. I find that people treat “Do Not Disturb” as a way to facilitate asynchronous communication (“Message me when you’re not busy and we can talk about this…”) whereas people generally do not message you at all (unless it’s an absolute emergency) when you are offline. Obviously, culture varies from company to company, but this is my own observation.  I think this is because “Do Not Disturb” communicates “I am here and will eventually be free sometime soon” and being offline sends the message that there is a really strong chance you are nowhere near a computer and are unable to talk–which is an absolutely okay place to be at 8PM on a Friday night.

4. I end my day by thinking of the next day. What things will I do tomorrow (or Monday)? If something less than ideal happens, what can I do to make sure it goes more smoothly if it happens again? This one is a bit new to me. It sounds like new-age meditative type nonsense, but spending just 10 minutes mentally wrapping up my day (and writing it down) seems to make it a lot easier to walk into the next day than spend the same amount of time reactively trying to remember all the loose threads of the day before.

5. I close out all the various work-related applications I use. This includes any terminal windows, editors, any browser tabs pointing at my local dev environment or Github. It all goes and my laptop returns to its ordinary non-work mode in which I chat with friends, play games, write things, and browse non-work websites.

Addendum

I saw a few different conversations emerge from this article that brought up interesting other related things. One is the idea of not using the same device for work as you do personal things.  I think this is increasingly less common though with remote work. I don’t have an office I go to every day where I keep my “work” computer. My office is just as much my couch as it is some coffee shop in Reykjavik, Iceland.

In my previous job, I had a company-issued laptop and a personal laptop. And I traveled a lot all over the world. And it was very frustrating carrying two laptops because I’m a pretty small lady!  First world problems? Yes. But I’d rather squabble over the mixing and mingling of business-related applications and personal things than suffer sore shoulders all the time.

The second thing that kept coming up was the idea of working during your personal time off. I don’t think I have ever officially Worked™ while taking time off work, but I’m guilty of checking e-mail and getting all strung out over “oh my god someone is touching my PR–why? what? what are they doing? why is this happening?” or “What happened during this meeting that I missed? Were important decisions made without me?” I don’t really think this behavior is in alignment with “Superhero Mode”. It’s more the result of a person having control issues (note I didn’t say developer, because it’s not strictly a developer problem). I think allowing yourself to stop being a helicopter mom to your own job gives you a sense of trust that you can walk away for a moment.

What things do you do to disconnect at the end of your day? What things do you do to help you reconnect the next day? Have you experienced Superhero Mode before and if so, were you also a victim of Imposter Syndrome? Comment below.

Saying Goodbye to Someone You Loved and Yet Never Met

Many people who know me personally know that I recently lost a twin pregnancy. I was pretty adamant about just sharing the experience because it’s kind of a shitty emotional experience to start and hiding it from the world only makes it feel worse, I think.

I found out I was pregnant at 5 weeks, and then found out they were twins at 7 weeks, just two days after my boyfriend of almost two years and I moved in together for the first time. They were little teeny, tiny twins with slow-paced heartbeats that seemed neither strong nor overly problematic.

I realize carrying naturally conceived unplanned twins is not something that most women will ever do,  so let me ameliorate your burning internal thought process: Yes, I was scared shitless and my reaction to seeing two embryos was to start irrationally sobbing.

Sobbing. Not out of sadness or happiness, but just shock. I have no twins in my family and I was statistically unlikely to conceive twins based on several factors. It didn’t help that at 7 weeks, one looked like an amoeba and the other like a cross of a tadpole and the little white guy from the game Fez. They didn’t look human so although internally, I felt their potential and love for them, what I expected to be a game-changing moment was anything but.

Screen Shot 2015-07-23 at 11.27.58 AM

It was exciting in some sense. Like hey, there’s two of them so they’ll have that linguistically interesting “twin talk” thing and they’ll have that close bond that only two people who share one womb can have–something I’ll never understand but surely they would. But, of course, also scary because I had no idea what it meant for my career as a software engineer. Or financially how I would afford the likely possibility that these babies would be born prematurely and spend time in NICU. Or how my naturally very petite body would manage to safely grow two little watermelons–since I was already experiencing some issues with my heart as a result. I was scared but in love with them, for sure.

But at a 9 week ultrasound, we found out they hadn’t been growing and had passed shortly after the first ultrasound. My body did not recognize that the pregnancy had ended. I was recommended to have a dilation and curettage surgery to remove them.

This was an emotionally painful process, even for an unplanned pregnancy, but I’m a fairly logical person so I look at this loss positively: because it illuminated an area of life I never really had put extensive consideration into.

I’m 30 years old, almost 31, and have always felt indifference to motherhood. I get impatient with other people’s children. I always assumed I had no maternal instinct. I had a pretty sad childhood in a deeply broken family and have always felt somewhat challenged by the idea of introducing a life into a world knowing there was potential for me to cause it as much pain as was allotted to me.

But, contrarily, knew there was a good chance I might be a kick-ass loving, compassionate mom who made sure her kid saw the world young, learned early, was well-cultured, well-mannered, had lots of friends, and was treated fairly and with respect. This is a tall order and takes a lot of effort, and I know it.

I write this from the unpopular side of someone who before pregnancy never yearned for a child. Who, upon finding out she was pregnant, immediately focused on the selfish aspects of what I felt was taken away from her: independence, financial freedom, fun, her ability to drink wine, craft beer, or cold brew coffee, take hot baths, do hardcore crossfit, ride a bike more than half a mile without needing to stop to dry heave, use ibuprofen and other common medicines, or eat goat cheese or unpasteurized soft cheeses.

It took time for me to look past these emotions and fully embrace what positivity also surrounded it–things that are supposedly natural to others but took deep introspection to extract out of my own heart. Once I found those emotions, I found a new part of myself who was a stranger laying in wait. And it was really eye-opening.

That person inside revealed to me that my pregnancy was something I owned and was in control of. That my children, although in many ways defined by nature, are shaped by the attitude I have when they’re inside of me and later outside of me.  They are a byproduct of me and another person and whatever relationship is fashioned between the four of us is not the same as any other person’s relationship with their children.

These children are gone today. Some day I might have another child or children. Those children will never replace these children. And that is what a miscarriage is like. It’s saying goodbye to someone who was with you for a while, who communicated to you through some weird telepathic force, who made you feel ways you never knew you could feel, who opened up a chapter of your life that you never would have been able to open on your own, who you loved deeply and unconditionally, and yet all the same…

You never got to meet, hug, thank, or even so much as say hello to them.

FullSizeRender

Imposter Syndrome is Like an STD

A long time ago I was in college.  I was in the computer science program at the University of South Carolina (go cocks) and I really hated it.

I’m not supposed to say that, though. I’m supposed to pretend I loved college and that I did well in it. But in truth, I was a fairly mediocre computer science student. I didn’t respond well to the blend of academia and technology and the setting made it really hard for me to understand practical use of a lot of the stuff I was supposed to be learning.

Even if I understood the concept of what was being taught, it didn’t really sink in–“We’re using ML, but what in the real world am I going to use ML for?” It’s not a rhetorical question–I really had no freaking idea.

I typically found that example material in lectures was too abstract for me and to some extent, alienated me. I felt apologetic for it without knowing why. Intro-level data structures classes explained how to implement a doubly linked list, but failed to explain why.  The intermediate level operating systems class explained what multithreading is but failed to give any contextual relevancy to when it is used in the real world.

Being a very hands-on learner, I expected this bewilderment to end in the classroom, but when I got my first job while still in college at 19, I was kind of blown away by how much was expected of me given I was writing PHP for $10 an hour. The 40-year-old team lead I worked with seethed vitriol and condescendence, asking me, “What do you mean you don’t know how to write a software requirements document?” I felt angry, but really not comfortable in my own skin enough to ask, “How can you possibly expect me to walk in the door of my first job knowing that without ever having had to write one before?” I felt angry. But I didn’t know who to feel angry with.

And although I really feel like I learned so much in that job, I constantly was wandering into a place where I was about to break down and give up. I worked with a friend who was very talented with PHP specifically, but I was more of a jack (jill?) of all trades and it seemed to work to my disadvantage.

Ten years later, the idea of giving up based on that one interaction sounds ridiculous to me, but I can time travel and remember the quivering feeling in my gut and the tears welling up in my eyes where I really didn’t know if I belonged and I felt no close comfort that things would work out. People expected the world of me but at the same time, no one expected anything of me. And that’s a horrible feeling to harness in your soul.

Imposter Syndrome is common in an age where you need “5 years of Swift experience” and so many companies hire entry-level positions as unpaid internships. But, the really shitty thing about Imposter Syndrome is that it’s like herpes. It never really goes away. And occasionally you’ll get flare-ups of it. And the most you can do is kind of rub ointment on it or whatever it is you do to deal with herpes (side note: I don’t have herpes so this is probably a terrible example).

What I mean is that once you’ve had the experience of knowing what it feels like to feel like you’re not good enough, you’ll always know what it feels like to feel that way. And when all the conditions around you are just right for it, you’ll feel that way again until you can soothe the ache and burn, or distract yourself enough to ignore the pain.

People have paid me to be a developer for 11 years now. I know a lot of things I didn’t know 11 years ago. And occasionally people say nice things to me that imply that I have, to some degree, some inkling of talent in what I do.  Likewise, I’ve had people be really rude to me as well. But the older I get, the more I realize my own self-worth and can excuse the fact that people on occasion will hang you if you’re willing to give them the length of rope to do it.

And somewhere in-between, occasionally I see behind people’s eyes imaginary things, looks of doubt and hesitation.  It’s a mirror of all the things I think of myself and all the self-ridicule for the things I want to know but maybe never will and all the mistakes I make that I think people are super-aware of when they’re really not, and they’re really thinking the same of themselves.

What drove me to write this wasn’t my own experiences directly, but those of newer developers–both in terms of people who are just learning and people who are just starting off from what they have learned. Due to the line of work I’m involved in, I am constantly an observer to people taking their first metaphorical steps on the paved road leading to the rest of their years. For a long time, I didn’t really pay attention to it, but these days I do and it’s breathtaking in some way.

As developers, we’re often so focused on where we are in our own experience that we don’t really pay attention to the way we got there and what mighty triumphs we sieged glory in to get there. Do you remember the first line of code you wrote? The first time you compiled something? The first time you committed code to a repository? The first time you ever deployed something to a production environment? Do you remember what it felt like to not know something and feel dumb for it and now you can’t imagine not knowing those things?

Every time you interact with another developer is a moment in that person’s story and is something that will manifest within them for the rest of their lives. From this remember these things:

  • Your life as a developer is a continued learning experience that doesn’t ever end.
  • Every time someone else doesn’t know something you know is a huge opportunity for you to proliferate knowledge. And the way you choose to do that and your attitude towards it will determine how well structured that foundation is.
  • Imposter Syndrome is like herpes. Most of the time it lies dormant in us, but it uses negativity and bad attitudes as a conduit for spreading. Don’t be the jerk that passes it on to others.

 

Food Science: Maté (or Yerbamate)

When I was in Argentina, one of the most widespread cultural phenomena that I encountered was the maté. Maté is popular enough by now that it has reached the United States. You may have seen bottled beverages labeled as yerbamate–that’s maté, brewed into a cold beverage… usually mixed with some other ingredient for flavor, like mint or pomegranate.  The taste of maté on its own is a unique, acquired taste. I’ve never smoked a tobacco cigarette in my life, but I wouldn’t be shocked if it were similar in flavor.

Anyway. The way we do maté in the US is wildly different from how South America does it! In the US, we are grab-n-go Starbucks consumers by day and reserve social beverage imbibing for beer. In Argentina, however, it is commonplace to hang out with friends and share a maté. This means drinking from the same vessel and passing it around the group. If I had to compare it to something easily familiar to Americans, I’d say it’s like sharing a joint with your friends… except, you know, with less legal implications.

So here’s a walkthrough on what maté is all about!

 

IMG_0589

These are the “basics” of a maté. The maté comes in loose leaf form, usually packed into paper sacks like you might purchase flour. There is a thing called “maté cocido,” which is “cooked maté” and that’s served in satchels, but I think that’s a huge cop-out and I wouldn’t recommend it.  The leaves here are very dry and shredded, kind of like a dusty oregano.

The wooden bit to the right is called a calabaza de maté or, simply, a gourd. You can get these gourds made from a lot of different materials. Some people prefer ceramic or silicone gourds because they are much easier to keep clean. Mine is  actually a gourd and the inside of it kind of looks like a hollowed out pumpkin. You’re supposed to keep these things dry or they grow mold on them very easily (which is why people prefer the ceramic and silicone variety!).

The two things on the bottom are bombillas (in Argentina this is pronounced bohm-beesh-uh, everywhere else bohm-bee-yuh). You only need one for a maté but I included two to show the different types you can use. These are used as a straw, except they don’t open on the bottom–they’re effectively filters, allowing the water to get through without you swallowing maté leaves. The one on the top is a bit more decorative than the bottom one, but both work great :)

You can get all of these supplies from Amazon, however, I did find a really cool international grocery store near me that sold all of these things as well, so they’re not hard to come by and are pretty cheap (everything above shouldn’t cost you more than $10 USD).

Making a maté is not at all like making a tea! You want to heat your water to about 80 degrees fahrenheit or 26 degrees celsius. If you heat it any higher than that, your maté will taste bitter and gross!

First, you fill your gourd with the maté. It should go almost to the top.

IMG_0591

 

It can be kind of messy! And as I said before, dusty. The dust is fine, but you don’t want to drink that, so the next step helps eliminate that. If you’ve ever cooked rice in a pot, you’ve probably used your fingers to help clean the rice and filter out extra starch. This is similar. Place your hand flat on the opening of the gourd so that the opening is completely covered and flip it over a few times. This will sift a lot of the dust out and it’ll end up on your hand like so:

 

IMG_0593

 

You can just wash this off. You don’t need it for anything! At this point it’s time to put your bombilla into the gourd. You push it down straight at first and then move it a little so the end of the bombilla is touching the other side. Your bombilla will basically look like it’s sitting diagonally. Explaining this makes it sound more complicated than it really is, so here’s a picture:

IMG_0594

 

Pretty obvious, right? My gourd here doesn’t have enough maté in it in this picture, but this is how the bombilla should look. At this point, pour your water in. You want the water to go all the way to the top. Once you’ve filled it, it’s time to drink it! Use the top of the bombilla like a straw and drink until there’s nothing left to drink.

Refill the calabaza with water and pass it on to your friend. They’ll drink out of the same gourd and bombilla. Make sure you take lots of photos of their facial expressions as they react to it for the first time! Keep refilling until you’re done or out of water.

Maté doesn’t have caffeine in it, but it does have something called mateine, which is from the same family of psychoactive ingredients… it works essentially the same as caffeine. You can find a lot of material online from people arguing on both sides that it’s not the same. Some say mateine makes you more relaxed than caffeine or that you need more mateine to get the same effect as caffeine. Unless you plan on taking like 20 hits of the gourd or just flat out cannot have caffeine, I wouldn’t be concerned. It’s no different from drinking a cup of earl gray or a cup of slightly weak coffee (if you’re used to double-shots of espresso, this will do nothing for you, nor should it be your primary intent for drinking maté!)

Would I recommend maté? Sure. It’s a fun socializing activity if nothing else.