The Pipeline is Full of Acid

This blog post originally appeared on 8th Light’s Blog

Last week, my co-worker Doug Bradbury posted on the 8th Light blog to ask about gender equality on programming teams. I’ve had some thoughts about his post for a couple of days, but I’d like to take a step back first. Before we ask whether our teams would be srtonger with more diversity, we should ask why our teams lack diversity in the first place.

This past spring semester I taught a Girls Who Code club class at The Chicago Tech Academy. It was an incredibly rewarding experience. Being given the opportunity to teach a group of high school girls some basic programming skills and see them flourish and get excited over it nearly brought me tears of joy a couple of times. However I started thinking that putting a bandaid on the problem, simply teaching girls to code, isn’t going to solve it. There are amazing women programmers who have still been threatened, sent death and rape threats, pushed out of the field, and have left technology all together. Being able to program didn’t help them. Being able to write code, even write code really well, didn’t prevent it from happening.

Before we can start asking why we need more marginalized folks on our teams, we have to ask how we can fix the toxicity that is the technology workforce. Throwing more marginalized people on our teams but never addressing the root factors, the ingrained sexism, misogyny, racism, homophobia, transphobia, and ableism, means we’re putting the responsibility of fixing the culture solely on those who are most affected by it.

We already know that the attrition rates for women in technology are way too high. Why do we think that just adding more women to our team will solve this problem? I never hear anyone say that they should fix their totaled car by adding a new coat of paint, or giving it a new set of tires.

I’d be lying if I said that the thought of leaving the technology field hasn’t crossed my mind more than once. Navigating online and offline spaces is very different as a woman. I’ve been harassed, stalked, and threatened when I denied advances from men at conferences, Meet Up groups, on Twitter, and email. These are spaces that many people take for granted, and in many cases these are the tools that professionals use to network, find a job, and even just make friends. When someone feels uncomfortable or unwelcome in a group, they’re unlikely to continue showing up. And when they don’t show up to these public settings, their professional career suffers because they don’t have the same opportunities to advance. Many marginalized people leave the field entirely because of this.

To answer Doug’s question: no, gender equality isn’t enough. But maybe not for the reasons that you think. Simply demanding a ratio to fulfill some diversity quota isn’t going to fix the broken culture that we work in. Adding more women to our teams, adding more marginalized folks to our teams, and patting ourselves on the back isn’t helpful, and it’s not a solution.

For members of the dominant group in the technology field (a white, straight, cisgender, heterosexual male), questions about diversity can quickly verge on thought exercises, questions that feel good to ask. Instead, let’s ask questions that make us uncomfortable. Instead of asking why more women on our teams would be good, let’s ask why there aren’t women on our teams already. Instead of saying we should focus on individuals and not on entire groups of people, let’s ask why all of our recent hires are from the same group of people. It’s great to get more marginalized people into the technology field, but if we’re not actively working to remove the acid from the pipeline, what’s the point?

If you’re interested in helping to fix the toxic culture, check out my website: Days Since Last Tech Incident for resources, blog posts, and information on how to do just that.

Framework Whipped

This is a response to Robert Martin’s disgustingly misogynistic blog post, called “Framework Whipped”, it’s since been taken down, but my criticism still stands

Robert Martin has rewritten his post, Framework Bound[2]. He has also issued this apology.

Frameworks are powerful tools, I’d say people can’t be tools, but if you write a blog post comparing women to frameworks complete with sexist tropes you might be a tool.

The relationship between a programmer and a framework is similiar to the relationship between a programmer and a framework, or a programmer and a hammer, or a programmer and a power drill, or a programmer and a tool.

The relationship between an executive and an administrative assistant is similar to the relationship between someone in power and someone who answers to them. These are real people, and power dynamics come into play. But let’s be real, when you say executive you mean man, and when you say administrative assistant you mean woman.

Finishing off the first section with the short sentence, we marry our secretary. As if that’s comparable to using a framework? Ah, women, they’re just replaceable tools, and in a few months, or years, you can just upgrade to the new model, the new version, just like you can with frameworks right?

Your metaphor is spot on, if you believe that women aren’t people.

I don’t even want to touch on your use of the word “harem” as your header for the next section. But let’s dig into that, shall we? Since I don’t think you’re talking about the part of a Muslim residence reserved for women, I’m going to assume you mean the “tongue in cheek” version, the version where a group of woman is associated with one man, I guess collecting women as if they’re objects, or frameworks does fit that definition, gross. Let’s move on.

Using a framework requires a significant commitment, yes. You allow the framework to handle some, if not most, of the heavy lifting for you, and you have to compromise on some of your conventions possibly. You might sacrifice some speed for conveience, for example.

Is this a trap? I suppose if you went into it thinking that there wouldn’t be compromise, that you wouldn’t have to adjust your way of doing things. But is that the fault of the framework?

I’ve never had a framework smile prettily at me, or entice me to move in closer, if you have you might want to step away from your computer for a while.

I guess if you view a heterosexual marriage as one where the man delegates tasks to the woman and she is obendient and subservient, than your metaphor sticks. I guess if the thought of allowing the woman to do any of the heavy lifting is just preposterous your metaphor is fantastic. I guess if you view women as objects, as not quite people, as tools to use for clickbait, for getting a point across, as literary devices, your metaphor is fucking fantastic.

Calling it framework whipped is funny though right, because if a woman gets to dictate to a man or gets to call the shots than he’s whipped. This is grade A humor over here folks. When the roles are reversed it’s not so desirable anymore is it? Hmmm, wonder why that is?

And can we please talk about how fucking disgusting the use of the word concubine is? Comparing frameworks and code to concubines undermines the real pain and suffering that women who were, and are, concubines face. Women in pain, women suffering, women are not your literary metaphors. If you need to rely on sexist languages, and sexist tropes to get your point across, your point fucking sucks.

And I know, you were trying to be edgy, and hyperbolic. It’s just so original. No one has ever used woman as a punchline, no one has ever taken away women’s autonomy and compared them to objects. It’s so cutting edge, so bold of you to aim so high.

As someone who works at 8th Light, someone who is a feminist to their core, who works to break down the systematic barriers in technology, posts like this on the blog of the company I work for undermine what I do.

Robert Martin has a platform bigger than what I could ever hope for. Even if I wanted to I couldn’t silence him, I couldn’t hope to silence him, his platform is huge. All I’m asking is that he considers who is affected when he posts things like this on a company’s blog.

Is this what you want 8th Light to represent? Posts like this one, and this one, and this one, and this one, and especially this fucking one all make me as an employee feel uncomfortable, undermined, and confused. Posts like these belong on a personal blog. They don’t represent how I feel, or how I hope the company at large feels.

Ruby on Rack

Last Friday I gave a smalltalk at 8th Light University about Rack. I’ve been really interested ever since doing my Java HTTP server to understand how frameworks, like Rails, deal with requests, responses, and routing.

The original idea I had for the talk was to track a request through Rails. I wanted to see what happened from the moment a user clicked on a link, or submitted a form in the browser, to when the response was rendered. As I dug more through Rails source code I found out that the part that ended up being the most interesting to me was all the stuff that Rack provided, the middleware, or the stuff that happened between sending the request to the server and returning the response to the client.

What is Rack?

Rack is the minimal, modular, and adaptable interface that Ruby frameowkrs like Rails and Sinatra are built on. Christian Neukirchen is the author of Rack and in a 2007 blog post titled: “Introducing Rack”Christian talked about how he was exploring different frameworks and found that there was a bunch of duplication between them. The goal of every framework is basically the same, to receive a request and return an appropriate response.

He thought there had to be a better way to do this, every framework developer shouldn’t be writing their own handlers for every web server they want to use hoping that their users are satisified with the choice that they do make.

In comes Rack. Christian outlined his goals of Rack to be this:

“Rack aims to provide a minimal API to develop web applications in Ruby, for connecting web servers supporting Ruby (like WEBrick, Mongrel, etc) and Ruby web frameworks (like Rails, Sinatra, etc).”

A Minimal API

Informally, a Rack application is something that responds to call:

This, while not using the Rack gem, is a “Rack” application. Since a lambda responds to call this meets the requirements of being a Rack application.

It takes a single argument, the environment:

The environment is an instance of Hash, it contains all the information about the request, #call returns us our response. A response is made up of three things:

  • 1. The status code 200
  • 2. The headers: {"Content-Type => "text/plain"}
  • 3. The body: ["Hello, world!"]

Connecting Web Servers

As I said above, before Rack, Ruby framework developers were writing their own handlers to deal with web servers. This meant frameworks were opinionated about the web server that they used, users of those frameworks had little to no say in what web server they could use when using that framework.

Rack helps out a lot in this regard. Rack abstracts away the common web server functions, like parsing an HTTP request or HTTP response. Rack also provides a lot of libraries for commonly used things like query parsing, or cooking handling. This means that Rack isn’t opinionated about web servers, there are handlers for almost every common Ruby web server, including WEBrick, Mongrel, Thin, and Puma to name a few.

Rack provides a standard way for Ruby applications to talk to web servers.

However, you could run this with any of the handlers that Rack has already provided for you.

Rack also abstracts away that server stuff that we don’t really want to have to deal with if we’re building a framework, or even just creating a simple application.

Abstracts Away Server Stuff

This is from the WEBrick handler. We can see that handling ports are taken care of (options[:Port] ||= 8080), the actual starting of the server (@server = ::WEBrick::HTTPServer.new(options)), initializing the servlet (@server.mount "/", Rack::Handler::WEBrick, app), and running the server (@server.start). Rack does all of this for us so we don’t have to worry about it. And if we get sick of using WEBrick we can switch over to using Thin, or Mongrel without having to change any of our framework or application code.

Parsing HTTP Requests

If we take a look at Rack’s Request class we can see that Rack parses the env hash to give us back useful information. We don’t have to worry about parsing out the nasty env hash anymore, and yeah, it’s pretty nasty:

Parsing HTTP Responses

Rack also parses HTTP responses for us, looking at the Rack Response class, we can see that there is a nice interface to create our Rack responses. We can set headers, and cookies, and we even have some useful defaults. (status=200, for example).

Ruby Web Frameworks

Many Ruby frameworks utilize Rack. If you’ve done any Rails, or Sinatra development, you’ve used Rack.

Rails and Rack

In the RailsGuides there is a section that explains how the rails servercommand works and a bit of code:

Basically rails server creates a Rack::Builder object and starts the webserver for us. This is the Rails version of Rack’s rackup script.

Sinatra and Rack

From Sinatra we have this:

This also creates a Rack::Builder instance, it provides all the middleware set up and the given app as the end point.

Of course there are many more ways that Rails and Sinatra use Rack, so it’s worth digging into the source code a bit to see. Knowing about Rack can also help to remove some of the “magic” around Rails.

Rack Middleware & Rack Applications

Rack’s simple protocol makes it easy to compose powerful applications by stacking Rack apps and middleware on top of each other. But what exactly is the difference between Rack apps and Rack middleware? They both seem sort of the same, it’s a thing that responds to #call. The key difference is that Rack middleware takes an application as an argument on initialize, where a Rack application does not. This means that Rack middleware has knowledge of the Rack application and is able to do things to it at call time.

Middleware

Rack middleware is a way to implement a pipelined development process for web applications. Middleware can do anything from managing user sessions, to authentication, to caching, to just about anything else. Since Rack middleware has access to the Rack application at call time we can do things to the request before it gets sent to the server, and do things to the response before it gets sent back to the client. Rack middleware comes between calling the client and the server, this is where the name “middleware” comes from, it happens in the middle of all that goodness.

In the above example I’m modifying the path info to make the application always think that env['PATH_INFO'] is /foobar. This is something that middleware can do (although, I’m not so sure you’d wantto do this. :)).

Rack middleware always us to process the request before sending it to the server, and process the response before returning back to the client. Things like Rack::Runtime take advantage of this.

If you’re curious about what middleware your application is using you can run rake middleware in your application directory and see a list of all the middleware that is being used.

Wrap Up

Now that you know a bit more about Rack (hopefully), you might be able to see some of it’s power. We can quickly create web applications using just Rack, when things like Rails are too big for our needs. Knowing about Rack also gives us the ability to be able to remove some of the magic surrounding Rails, and can even allow us to debug easier and with more confidence.

I’ve forked a version of Rack and added some useful puts statementsthat helped me to understand Rack and what role it was playing. It might be useful for you as well to point your Rack gem at my repository so you can also get some logging in your console to see what Rack is doing for you.

Pairing Tour: Week One

As you might already know if you’ve been reading my blog, or following me on twitter, at 8th Light we have apprenticeships. I’ve been a resident apprentice since April 8th, 2013. During the apprenticeship you are paired with a mentor, and undergo an intense period of learning and coding. For me, I had no software development experience coming into 8th Light. I had done some HTML/CSS and a little bit of PHP/MySQL (I set up quite a few WordPress sites for myself, friends, and family when I was younger).

Everyone’s apprenticeship is a little bit different. The core concepts are the same, we learn how to write clean, well-tested code. We learn about Agile methodologies, and from time to time we get to pair on projects with other apprentices. However, every apprentice goes through roughly the same final month.

When reaching the end of the apprenticeship we get to “roll our board”. Rolling the board involves being randomly assigned eight craftsmen that will act as the review board for that apprentice. During the last month of the apprenticeship the first two weeks are spent on a pairing tour. The pairing tour is when an apprentice gets to sit down and spend an entire day pairing with each of the people on their board.

The First Week

I finished the first week of my pairing tour last week, and started on the second week of my pairing tour today. Last week I paired with Patrick,KevinDave, and Mike.

So far on my tour I haven’t been writing code everyday, but I have gotten to better understand some of the roles of my co-workers. For example, when I paired with Dave I attented two IPMs, helped write emails to clients, and learned more about how our studio projects work. I also got to help with some of the beginning stages of writing a proposal for a would-be client.

When I paired with Mike we spent a lot of time working on internal things at 8th Light. Things like making sure all of our clients were properly staffed, and figuring out how to staff incoming clients. I didn’t know much about that process, so it was really interesting getting to see that side of things. I also got to go over my Ruby on Rack smalltalk with him and got some good feedback before actually giving the talk.

When I paired with Patrick and Kevin I got to work on code. It was interesting because both of the projects were in Ruby, and I had spent the last five weeks in a Clojure stack. Coming back to Ruby wasn’t as difficult as I worried it might be, and I feel I was able to add value to both of those projects in the limited amount of time I got to work on them.

Lessons Learned While Pairing

One of important things I took away from last week’s pairing tour was understanding that not only do we as consultants need to be able to have knowledge of the language we’re writing, whether that’s Ruby, Clojure, Java or some other language, we also need to have knowledge of the business domain of the client. Having knowledge of the business domain means that we can talk in terms that are meaningful to our client to ensure we’re on the same page. It also means that when we have a feature we need to build out we can understand the use case of the feature in a way that is important to the client.

As consultants, we roll on new projects and really need to get up to speed on what’s going on quickly so that we can start adding value right away. This means understanding that we’re not going to get the entire context of things. It’s important to understand that we may not know the entire context of something, and that’s okay.

There isn’t always time for deep dives, and we’ll never be able to hold the entire system in our head coming onto the project initially, and maybe not ever, and that’s okay. It’s important that we understand the business domain of our client, so we can wrap our head around what our immediate tasks are, and maybe what they’re touching, but digging into multiple degrees of separation will just be a rabbit hole that we shouldn’t go down. That’s not to say that explorations are out of the question, and that’s not to say that getting clarification on why a feature is important, or what it’s use case is isn’t important, because it definitely is, making sure we’re on the same page as our clients is our job as consultants.

Week Two Starts Today

This week starts the beginning of my second week of my pairing tour. I’ll be pairing with MylesArlandisColin, and Chris. This week will probably be a bigger emphasis on code and less on administrative things so I’m looking forward to being able to participate in some ping-pong pairing.

Conditional Binding in Clojure

I’ve been working on a client project in Clojure for the past month to prepare me for my upcoming pairing tour and challenges. This project has been a blast to be on, and I’ve definitely leveled up my Clojure skills.

One of the stories I picked up this week was for doing some autocompleting based on some given data in the database. We already had a very specific autocomplete function for some exisiting autocomplete functionality. Adding the new autocomplete functionality meant that I was writing additional functions that looked nearly identical to the existing function, except for a very minor difference in each function so it would use the correct suggestion function for the given entity.

When it comes to refactoring I tend to stick to the three strikes and you’re out type of mindset. If I repeat myself twice, that’s starting to become a smell, but extraction isn’t quite necessary yet (this varies on a case-to-case basis, of course). However, once I have three functions that look nearly identical, it’s time to make them as general as possible to avoid the duplication and to DRY up my code. After writing almost the same function for the third time I knew it was time to extract and generalize.

Conditional Binding

The actual scenario of autocompletion isn’t relevant to the code I’m going to share today. I found myself wanting to be able to conditionally create a binding based on an argument the function received. Something that I could do in Ruby like this:

This is a pretty contrived example, but this is more of less what I wanted to duplicate in Clojure. I wanted to give my general function an argument, and based on that argument it would create a binding that I could use to do something in my function.

Before I generalized the function I had three functions that looked like this:

As you can see, these functions look extremely similar to each other, the only difference between them is that they use different entities to get suggestions, and have different keywords in the body.

I wanted to create a function that could do something like I did with the Ruby example above.

That’s roughly what I wanted to be able to do, I wanted to create a new binding (represented by the entity-suggest variable), and conditionally change what the value was based on the keyword argument. After I had that binding I wanted to use it.

I was able to achieve this in Clojure like so:

This allowed me to remove those three functions in favor of this one. The function that calls this function now uses two arguments instead of one, the keyword, and the original argument that it always passed in.

Wrap Up

I’m quite happy with the generalized function. When I first approached Clojure I was frustrated because I had a difficult time expressing myself, I knew how to do what I wanted in Ruby but I couldn’t translate that over to Clojure.

Learning a new programming language is a lot like learning how to speak a new language. You know what you want to say in your fluent language, but the translation isn’t one-to-one, so you have to learn new syntaxes and new grammars to do the translations in your head. I know very little Spanish, but when I took classes in high school I never got to the point where I was able to hear a Spanish sentence and know what it meant without having to mentally translate it to English.

Learning Clojure has been a lot like that, I’d read a function and immediately try and translate it to Ruby so I had a frame of reference. I’m finding myself being able to think about things in the scope of Clojure, I don’t have to do those mental translations as often anymore, and I’m more fluent at speaking about Clojure, and using context clues to figure out what’s going on without having to do the translation to Ruby.