I really love this awesome infographic that Jess Gartner created for the recent RailsGirls Baltimore event, showing what we learned in organizing it and what the experience was like for everyone involved.
The best thing about it, for me, is that it's a list of "to-dos" for making inclusive events. I feel like there's already a lot of information about what not to-do (although sadly, that information still hasn't reached many members of the tech industry, as Jess' previous infographic shows) and it's nice to get some specific, tactical advice about how to convert good intentions into reality.
Wednesday, March 13, 2013
Thursday, February 21, 2013
More ways to keep the American dream in America
I read Dave Troy's post Keeping the American Dream in America with interest. I agree with everything he says about needing to get aspiring entrepreneurs to focus on solving more important, technically-challenging problems instead of devising endless variations of incrementally-better consumer software.
There are other obstacles to achieving the kind of entrepreneurship Dave wants to see, besides the ones he mentioned. Those hard problems are going to end up being solved by older people not currently enmeshed in "McStartup" culture. Innovation in fields like healthcare, education, biotechnology, or government are likely to come from people working in those fields already. I'm thinking of people like Jess Gartner, a former schoolteacher who just received funding from Accelerate Baltimore to create an new product that will revolutionize the way we fund schools and track funding outcomes. That's not an idea that Dave's "Red Bull-drinking, Ramen-eating young programmers" could think of, unless they had worked as teachers.
To solve the "McStartup" problem, we need more entrepreneurs like Jess or my partner James Curran, people who have established a career and built up some work experience, who have firsthand knowledge of screwed-up situations that could be improved with new technology (using James hard-won expertise, we are attacking a tough problem in the online media industry).
Because these are also people who may have families, who may be the breadwinner, I have a theory that we could encourage more mid-career people to start or join serious startup companies by increasing our support for risk-taking behavior in the United States. Off of the top of my head, some ways to support risk-taking behavior would include:
There are other obstacles to achieving the kind of entrepreneurship Dave wants to see, besides the ones he mentioned. Those hard problems are going to end up being solved by older people not currently enmeshed in "McStartup" culture. Innovation in fields like healthcare, education, biotechnology, or government are likely to come from people working in those fields already. I'm thinking of people like Jess Gartner, a former schoolteacher who just received funding from Accelerate Baltimore to create an new product that will revolutionize the way we fund schools and track funding outcomes. That's not an idea that Dave's "Red Bull-drinking, Ramen-eating young programmers" could think of, unless they had worked as teachers.
To solve the "McStartup" problem, we need more entrepreneurs like Jess or my partner James Curran, people who have established a career and built up some work experience, who have firsthand knowledge of screwed-up situations that could be improved with new technology (using James hard-won expertise, we are attacking a tough problem in the online media industry).
Because these are also people who may have families, who may be the breadwinner, I have a theory that we could encourage more mid-career people to start or join serious startup companies by increasing our support for risk-taking behavior in the United States. Off of the top of my head, some ways to support risk-taking behavior would include:
- Better access to affordable, quality childcare: A big reason I can afford to take the risks I do is that we have a lot of nearby family help, and we were lucky to get our kids into an awesome, affordable preschool.
- More widely-available, affordable healthcare: I know someone who delayed starting his now-highly successful, real-world-problem-solving tech company because he needed to provide health coverage for his wife who had a pre-existing condition.
- Well-funded, well-managed public retirement system: Middle-aged people might be willing to take more risks if they felt they didn't have to save every penny in order to stave off penury in old age.
- Restored public support for higher education: Someone who graduated from college years ago with outstanding, crushing debt is probably not going to jump out of a comfortable job to start a tech company.
Friday, February 1, 2013
Ignite Baltimore Proposals and Grants
We're now accepting proposals to speak at Ignite Baltimore #12 on 3/28, and one of my co-organizers, Neal Shaffer, wrote a comprehensive explanation of the kinds of talks we're looking for. Please consider submitting your idea for consideration! Proposals are due 2/17/13.
We also use the ticket proceeds to give out Ignition Grants at every Ignite, aimed at funding a new projects in the city. This time we're giving out $4500 in grants. Grant applications are due 2/22/13. If you've got a worthy idea that needs funding, please apply!
We also use the ticket proceeds to give out Ignition Grants at every Ignite, aimed at funding a new projects in the city. This time we're giving out $4500 in grants. Grant applications are due 2/22/13. If you've got a worthy idea that needs funding, please apply!
Monday, January 28, 2013
Invitation to RailsGirls
I'm helping organize RailsGirls Baltimore on 3/2 to introduce computer programming to girls and women in the Baltimore area. No prior experience is required! It's a fun day of learning new skills in a small group with a coach helping you progress through a series of exercises.
Please help me spread the word as much as possible. We'd like to have as many women attend as possible!
Details are here:
Hope to see you there!
Thursday, January 24, 2013
Rspec matchers for Sidekiq
I've been writing a lot of specs lately to make sure my code properly enqueues Sidekiq jobs. I ended up duplicating a lot of code, and after reading the Rspec custom matcher documentation, I decided to DRY up the tests using some of my own matchers. The code is here in my "power tools" gem. Enjoy!
The tests end up looking like this:
The tests end up looking like this:
MyWorker.should have_queued_job(2) Collector.should have_queued_job_at(Time.new(2012,1,23,14,00),2)
Friday, December 21, 2012
Thoughts on programming AdStaq's culture
We just posted the Careers page for my new startup, AdStaq.com. We're looking for smart developers of all backgrounds, junior and senior, who want to be part of the founding team. We're primarily looking for people in the MD/DC/PA/VA or NY regions because at this stage we need to get together frequently to compare notes. Later on we'll become a more global/virtual company.
Hopefully it's obvious from reading that page that I've been thinking very deeply about the kind of programming culture we want to build into the company from day one, influenced by all of the reading I've done over the past several years and all of my work experiences as a Navy officer, tech company employee, and founding CTO. I want to create an ultra-professional, stimulating environment that provides fun and meaningful opportunities for programmers who also have a life outside of coding and want to get home and see their families every night.
My favorite line of that page is "no weekly status updates", which someone asked me to clarify. I'm not saying "programmers get to work in isolation without communicating what they're doing". I'm saying we're never going to make people do that kind of awful busywork just to make management happy. Instead we'll keep track of our progress using other tools, like reviewing commit logs and good old-fashioned one-on-one meetings.
Ben Horowitz just wrote a good post about creating the right culture for a startup. It's early days for AdStaq but I think our cultural motto might end up being something like, "We remove all software defects immediately and fix whatever allowed the defect to occur" (we need to come up with something snappier like "don't just fix the bug, fix the process"). For example, right now, James just emailed me a bug in a secondary screen in our app. He said it's not a big deal to fix immediately, so I could blow it off for a few weeks, especially since I'm building a really cool new feature I can't wait to release. But I know better than to allow a bug like this to hang around and get stale. I also know that a small investment of time to improve our test harness to prevent this bug from recurring will act like compounding interest, saving me a lot of time later. Most importantly, since we're a company that makes other software easier to use, we really can't afford to have low quality. We have to set the standard for ad tech company software quality.
We can't do it alone though - we need your help! If this sounds interesting, email me! Instead of a resume, send us some links to stuff you've worked on!
Hopefully it's obvious from reading that page that I've been thinking very deeply about the kind of programming culture we want to build into the company from day one, influenced by all of the reading I've done over the past several years and all of my work experiences as a Navy officer, tech company employee, and founding CTO. I want to create an ultra-professional, stimulating environment that provides fun and meaningful opportunities for programmers who also have a life outside of coding and want to get home and see their families every night.
My favorite line of that page is "no weekly status updates", which someone asked me to clarify. I'm not saying "programmers get to work in isolation without communicating what they're doing". I'm saying we're never going to make people do that kind of awful busywork just to make management happy. Instead we'll keep track of our progress using other tools, like reviewing commit logs and good old-fashioned one-on-one meetings.
Ben Horowitz just wrote a good post about creating the right culture for a startup. It's early days for AdStaq but I think our cultural motto might end up being something like, "We remove all software defects immediately and fix whatever allowed the defect to occur" (we need to come up with something snappier like "don't just fix the bug, fix the process"). For example, right now, James just emailed me a bug in a secondary screen in our app. He said it's not a big deal to fix immediately, so I could blow it off for a few weeks, especially since I'm building a really cool new feature I can't wait to release. But I know better than to allow a bug like this to hang around and get stale. I also know that a small investment of time to improve our test harness to prevent this bug from recurring will act like compounding interest, saving me a lot of time later. Most importantly, since we're a company that makes other software easier to use, we really can't afford to have low quality. We have to set the standard for ad tech company software quality.
We can't do it alone though - we need your help! If this sounds interesting, email me! Instead of a resume, send us some links to stuff you've worked on!
Thursday, November 1, 2012
Ruby Dependencies, Notifications, and Adjustments
Note: I originally submitted this article as a draft to the Practicing Ruby online journal. Gregory liked my concept but ultimately ask if I would mind if he wrote his own version. He did an awesome job and if you're interested in this subject I recommend you definitely read his article.
Introduction
Object-oriented programming helps organize your code in a resilient, easy-to-change way. This article aims to explore one of the concepts that trips up beginner and more experienced object-oriented programmers: how to sensibly connect a set of objects together to perform a complex task. How do you put instances of your information-hiding, single-responsibility-discharging, message-passing classes in touch with one another?
I became confused about the smartest ways to do this when I started building Ruby apps that involved fetch large amounts of data from external services. In these projects, a Rails or Sinatra web application acted as a facade for workers querying a large set of APIs. Each API was different from the last, requiring different approaches and different dependencies. Some APIs involved five or six different steps, and in some cases each step needed to be handled by a different object.
I felt I understand object-oriented programming pretty well, yet I struggled with specifying the relationships between objects so that each object knew just enough about its peers to get the job done. My style was inconsistent. Sometimes I would inject a dependency using the constructor, and sometimes I would use a setter method. At other times it seemed more natural to have an object directly instantiate new instances of whatever objects it needed, on the fly.
All of the code examples referenced below can be found in this gist.
Object Peer Stereotypes
All of this changed when someone turned me onto the book Growing Object Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce. The book has a chapter on object-oriented design styles, and includes a description of “Object Peer Stereotypes” that addressed my conundrum perfectly.
The authors divide an object’s peers into three categories: Dependencies, Notifications, and Adjustments (DNA). These are rough categories, because an object peer could fit into more than one category, but I found it to be a useful distinction. We’ll explore each of these categories as they pertain to Ruby code using an example from my real production code: a wrapper for Typhoeus I wrote called HttpRequest.
By the way, Gregory wrote about a related topic (what types of arguments to pass into a method) back in Issue 2.14. As your objects become more sophisticated you’ll find you end up passing fewer basic object types like strings, symbols, or numbers, and more of the Argument, Selector, or Curried objects that Gregory describes.
Dependencies
I wrote the HttpRequest class so that I could set on_success and on_failure callbacks (where Typhoeus only provides an on_complete callback) and to encapsulate my dependency on the Typhoeus gem, in case I want to switch to another HTTP library later.
HttpRequest objects have two Dependencies: the URL of the request and a set of options for telling Typhoeus how to make the request. Here's a link to an example of HttpRequest code.
Note that I’m supplying a default for the options argument, since it’s just a hash that gets passed onto Typhoeus::Request, and it’s something you’ll have available at the same type you have the URL. Because there is a sensible default (an empty hash), you could argue that this argument is more of an Adjustment, described below.
If options was a more complex object, something that might have peers of its own, I would probably treat it as an Adjustment. I find test-driven development really helpful in cases like this because often the tests can help you feel out which approach is more appropriate (which is the whole premise of the Growing Object Oriented Software book).
Notifications
In the HttpRequest example, success_callbacks and failure_callbacks are the notifications. Another object can register for success notifications like this.
Logging is another canonical notification example. Here’s a pattern I use a lot for logging.
Notifications can also be sent as arguments to a method call. I often pass a block for error handling. I find this usually involves fewer lines of code than returning a status object that must be tested for success or failure. Here's an example.
Adjustments
Most of my Adjustments involve component parts of a composite object. For the API-intense project where I’m using HttpRequest, I always have one class that has overall responsibility for getting all of the data we need for each API. That “master” class just does one thing: it coordinates the activities of a set of Adjustment peers, are of which are set to sensible defaults.
This also enables simple unit testing because you can so easily set the adjustments to mock objects provided by the tests.
If you use the strategy pattern, where peer objects make decisions for your object, your Adjustment might look like this.
It could be that AdminChecker is more of a Dependency than an Adjustment, depending on how many different kinds of AdminCheckers there are and how central admin-checking is to your code. If there’s no normal default for the admin_checker value, and if you really can’t make a DataFetcher without knowing what kind of checking policies it’ll be working with, you should probably inject your admin_checker in the constructor, marking it as an important Dependency.
HttpRequestService
There’s one other facet to my HttpRequest object that I thought Practicing Ruby readers might find interesting. Because Typhoeus is concurrent, you have to queue up requests onto a shared Typhoeus::Hydra object. The requests don’t run until you invoke the hydra’s #run method. I experimented with storing the Hydra object in various places and ended up creating a factory for HttpRequest objects called HttpRequestService, below. Can you spot the dependencies and adjustments? It doesn’t have notifications, but I could see adding some instrumentation to measure HttpRequest times.
Instances of the HttpRequestService end up as Adjustment peers for the objects responsible for fetching data.
Dependency Injection Containers
Rubyists generally eschew dependency injection containers but they complement the DNA style quite well. I use dependency injection containers as the single place where my code can pull in dependencies from different sources. These dependencies sometimes involve extra setup steps or massaging, depending on whether the code is running in production mode or not, and the container is a convenient place to consolidate that kind of housekeeping code. It often provides the sensible default for notifications and adjustments, and it’s an important part of the boot process for most of my Ruby code.
I’ve created a simple gem for this purpose called dim based on Jim Weirich’s article. If you’re interested in the topic, I highly recommend that article. Here’s a snippet of one of my container definitions.
Conslusion
Don’t hold too rigidly to these classifications; they’re more like heuristics. As Steve Freeman and Nat Pryce wrote:
When considering how to organize object peers I recommend you favor what’s most understandable and flexible, even if it means deviating from the DNA pattern.
Introduction
Object-oriented programming helps organize your code in a resilient, easy-to-change way. This article aims to explore one of the concepts that trips up beginner and more experienced object-oriented programmers: how to sensibly connect a set of objects together to perform a complex task. How do you put instances of your information-hiding, single-responsibility-discharging, message-passing classes in touch with one another?
I became confused about the smartest ways to do this when I started building Ruby apps that involved fetch large amounts of data from external services. In these projects, a Rails or Sinatra web application acted as a facade for workers querying a large set of APIs. Each API was different from the last, requiring different approaches and different dependencies. Some APIs involved five or six different steps, and in some cases each step needed to be handled by a different object.
I felt I understand object-oriented programming pretty well, yet I struggled with specifying the relationships between objects so that each object knew just enough about its peers to get the job done. My style was inconsistent. Sometimes I would inject a dependency using the constructor, and sometimes I would use a setter method. At other times it seemed more natural to have an object directly instantiate new instances of whatever objects it needed, on the fly.
All of the code examples referenced below can be found in this gist.
Object Peer Stereotypes
All of this changed when someone turned me onto the book Growing Object Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce. The book has a chapter on object-oriented design styles, and includes a description of “Object Peer Stereotypes” that addressed my conundrum perfectly.
The authors divide an object’s peers into three categories: Dependencies, Notifications, and Adjustments (DNA). These are rough categories, because an object peer could fit into more than one category, but I found it to be a useful distinction. We’ll explore each of these categories as they pertain to Ruby code using an example from my real production code: a wrapper for Typhoeus I wrote called HttpRequest.
By the way, Gregory wrote about a related topic (what types of arguments to pass into a method) back in Issue 2.14. As your objects become more sophisticated you’ll find you end up passing fewer basic object types like strings, symbols, or numbers, and more of the Argument, Selector, or Curried objects that Gregory describes.
Dependencies
“Services that the object requires from its peers so it can perform its responsibilities. The object cannot function without these services. It should not be possible to create the object without them.”
“...we insist on dependencies being passed in to the constructor, but notifications and adjustment can be set to defaults and reconfigured later.”
I wrote the HttpRequest class so that I could set on_success and on_failure callbacks (where Typhoeus only provides an on_complete callback) and to encapsulate my dependency on the Typhoeus gem, in case I want to switch to another HTTP library later.
HttpRequest objects have two Dependencies: the URL of the request and a set of options for telling Typhoeus how to make the request. Here's a link to an example of HttpRequest code.
If options was a more complex object, something that might have peers of its own, I would probably treat it as an Adjustment. I find test-driven development really helpful in cases like this because often the tests can help you feel out which approach is more appropriate (which is the whole premise of the Growing Object Oriented Software book).
Notifications
“Peers that need to be kept up to date with the object’s activity. The object will notify interested peers whenever it changes state or performs a significant action. Notifications are ‘fire and forget’; the object neither knows nor cares which peers are listening.”
In the HttpRequest example, success_callbacks and failure_callbacks are the notifications. Another object can register for success notifications like this.
Logging is another canonical notification example. Here’s a pattern I use a lot for logging.
Notifications can also be sent as arguments to a method call. I often pass a block for error handling. I find this usually involves fewer lines of code than returning a status object that must be tested for success or failure. Here's an example.
Adjustments
“Peers that adjust the object’s behavior to the wider needs of the system. This includes policy objects that make decisions on the object’s behalf...and component parts of the object if it’s a composite.”
Most of my Adjustments involve component parts of a composite object. For the API-intense project where I’m using HttpRequest, I always have one class that has overall responsibility for getting all of the data we need for each API. That “master” class just does one thing: it coordinates the activities of a set of Adjustment peers, are of which are set to sensible defaults.
This also enables simple unit testing because you can so easily set the adjustments to mock objects provided by the tests.
If you use the strategy pattern, where peer objects make decisions for your object, your Adjustment might look like this.
It could be that AdminChecker is more of a Dependency than an Adjustment, depending on how many different kinds of AdminCheckers there are and how central admin-checking is to your code. If there’s no normal default for the admin_checker value, and if you really can’t make a DataFetcher without knowing what kind of checking policies it’ll be working with, you should probably inject your admin_checker in the constructor, marking it as an important Dependency.
HttpRequestService
There’s one other facet to my HttpRequest object that I thought Practicing Ruby readers might find interesting. Because Typhoeus is concurrent, you have to queue up requests onto a shared Typhoeus::Hydra object. The requests don’t run until you invoke the hydra’s #run method. I experimented with storing the Hydra object in various places and ended up creating a factory for HttpRequest objects called HttpRequestService, below. Can you spot the dependencies and adjustments? It doesn’t have notifications, but I could see adding some instrumentation to measure HttpRequest times.
Instances of the HttpRequestService end up as Adjustment peers for the objects responsible for fetching data.
Dependency Injection Containers
Rubyists generally eschew dependency injection containers but they complement the DNA style quite well. I use dependency injection containers as the single place where my code can pull in dependencies from different sources. These dependencies sometimes involve extra setup steps or massaging, depending on whether the code is running in production mode or not, and the container is a convenient place to consolidate that kind of housekeeping code. It often provides the sensible default for notifications and adjustments, and it’s an important part of the boot process for most of my Ruby code.
I’ve created a simple gem for this purpose called dim based on Jim Weirich’s article. If you’re interested in the topic, I highly recommend that article. Here’s a snippet of one of my container definitions.
Conslusion
Don’t hold too rigidly to these classifications; they’re more like heuristics. As Steve Freeman and Nat Pryce wrote:
“What matters most is the context in which the collaborating objects are used. For example, in one application an auditing log could be a dependency, because auditing is a legal requirement for the business and no object should be created without an audit trail. Elsewhere, it could be a notification, because auditing is a user choice and objects will function perfectly well without it.”
When considering how to organize object peers I recommend you favor what’s most understandable and flexible, even if it means deviating from the DNA pattern.
Subscribe to:
Posts (Atom)








