Friday, April 20, 2012
Scala Test Plug-in for Sublime Text 2
Dev Days: Hacking, Open Source and Docs
Dev Days
Every month we have a "Dev Day" where engineers take a break from their projects and work on "other stuff". Most start-up engineering teams have a "Hack Day" where everyone gets to hack on anything they want as long as they ship and share it with the rest of the team. Of course we have Hack Days but we also have other types of Dev Days too. In fact, we have three types of Dev Days:- Hack Days
- Open Source Days
- Doc Days
Open Source Days
You know what Hack Days are so I'll move on quickly to Open Source Days. Just like most companies these days, Bizo uses a lot of open source software (OSS). We love OSS and the community of developers and companies that share it. Over the last few years, we've used plenty of OSS but we've also created and given back lots of code as well.Actually today is one of our Open Source Days so all the engineers are working on both new and old open source projects. You can check out our (growing) list of projects by visiting code.bizo.com. Over the years, we've created a lot of tools around AWS including s3cp, fakesdb, aws-tools (package of all CLI tools). We've also built a lot of stuff for Hadoop (Hive, etc) including csv-serde, gdata-storagehandler and our latest is a scala query language called revolute (still in development). In addition, we've have a wide variety of other awesome code including the awesome Joist, dependence.js, raphy-charts and other fun stuff!
Doc Days
Conclusion
Thursday, April 5, 2012
Implementation driven interfaces?
I've recently encountered some interesting pagination in the Google Groups admin interface. It starts off simple enough, nothing exciting here...
Instead of the usual 'Previous', we see 'First' on the next page.
Are they just being clever? Knowing that there's only one previous page? No such luck…

We've reached the end of the list. I hope you've found what you're looking for, otherwise start over from the beginning!

One has to wonder, who designed this interface? You can only go forward. If you overshoot, it's back to square one, then click, click, click… It's clear it does not have users in mind at all.
My guess is that it's based on some limitation in the backend storage or query mechanism. The system only allows forward navigation of query results, so the interface simply mirrors that…
What an incredibly frustrating experience! I'll never take simple pagination for granted again.
It's a good reminder to think about your users and how they will interact with the system. Mirroring the programming interface rarely works.
Wednesday, April 4, 2012
Capturing Client Side JS Errors on AWS
Background
Quick background, we have two major types of javascript that our customers and partners may use: analytics tags and ad tags. Both tags are javascript and share the same error capture code.
Another quick note is that we run on Amazon Web Services so this approach is based on some of these services including S3, CloudFront and EMR.
Implementation
Our client side JS is compiled from Coffeescript. I've created a couple of gists to show you what the error logging code looks like in Coffeescript.
Details
The example shows our ad tags trying to execute surrounded by a try/catch that captures the error and eventually results in loading an image appending the relevant error metadata.
AWS Details
The image that is loaded actually lives on CloudFront. The CloudFront distribution is setup with logging which means that requests are logged and delivered to a specified S3 bucket (usually within 24 hours). Every day we run an EMR job against the CloudFront request logs that generates a report summarizing the errors. And that is it. Pretty simple and this approach has worked for us.
Pre-emptive "this isn't perfect" response
Some of you may be thinking, "you may not get all requests!". CloudFront logs are not supposed to be used for 100% accurate reporting (although nothing is really 100%). In our case, we don't need to capture all errors rather we are looking for directional information.
Monday, April 2, 2012
Creating Plug-ins for Sublime Text 2
Create a new plug-in
import sublime, sublime_plugin class ExampleCommand(sublime_plugin.TextCommand): def run(self, edit): self.view.insert(edit, 0, "Hello, World!")
Make it do something cool
Run a command on the current file
def show_tests_panel(self): if not hasattr(self, 'output_view'): self.output_view = self.window().get_output_panel("tests") self.clear_test_view() self.window().run_command(" show_panel", {"panel": "output.tests"}) def clear_test_view(self): self.output_view.set_read_ only(False) edit = self.output_view.begin_edit() self.output_view.erase(edit, sublime.Region(0, self.output_view.size())) self.output_view.end_edit( edit) self.output_view.set_read_ only(True)
self.proc = subprocess.Popen("{my command}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
thread.start_new_thread(self. read_stdout, ())
def read_stdout(self): while True: data = os.read(self.proc.stdout.fileno(), 2**15) if data != "": sublime.set_timeout(functools. partial(self.append_data, self.proc, data), 0) else: self.proc.stdout.close() break
def append_data(self, proc, data): self.output_view.set_read_only(False) edit = self.output_view.begin_edit() self.output_view.insert(edit, self.output_view.size(), data) self.output_view.end_edit( edit) self.output_view.set_read_ only(True)
Using the "quick panel" to search for files, and opening files
def file_selected(self, selected_index): if selected_index != -1: sublime.active_window().open_file(self.files[selected_ index])
Create keystroke bindings
[
{ "keys": ["super+shift+e"], "command": "jump_to_scala_file" }
]
[
{ "keys": ["super+shift+e"], "command": "jump_to_scala_file",
"context" : [{"key": "selector", "operator": "equal", "operand": "source.scala", "match_all": true}]}
]
Conclusion
Resources
Official plug-in examples (sparse): http://www.sublimetext.com/
Official API reference: http://www.sublimetext.com/
https://github.com/maltize/
https://github.com/noklesta/
https://github.com/luqman/
https://github.com/rspec/
http://wbond.net/sublime_
Tuesday, March 13, 2012
A Short Script for Logging into Interactive Elastic MapReduce Clusters
My current solution is to allow myself to get distracted but to drag myself back to my EMR session as soon as it's available. Adding some simple polling plus a sticky growl notification to my interactive-emr-startup script does the trick quite nicely:
#!/bin/bash
if [ -z "$1" ]; then
echo "Please specify a job name"
exit 1
fi
elastic-mapreduce \
(... with all of my favorite options ...) \
| tee ${TMP_FILE}
JOB_ID=`cat ${TMP_FILE} | awk '{print $4}'`
rm ${TMP_FILE}
# poll for WAITING state
JOB_STATE=''
MASTER_HOSTNAME=''
while [ "${JOB_STATE}" != "WAITING" ]; do
sleep 1
echo -n .
RESULT=`elastic-mapreduce --list | grep ${JOB_ID}`
JOB_STATE=`echo $RESULT | awk '{print $2}'`
MASTER_HOSTNAME=`echo $RESULT | awk '{print $3}'`
done
echo Connecting to ${MASTER_HOSTNAME}...
growlnotify -n "EMR Interactive" -s -m "SSHing into ${MASTER_HOSTNAME}"
ssh $MASTER_HOSTNAME -i ~/.ssh/emr-keypair -l hadoop -L 9100:localhost:9100
One of my personal productivity goals for the year is finding little places like this that I can optimize with a short script. This particular one has rescued me from the clutches of HN more than once!
On Code Reviews and Developer Feedback
There's a great post from last week at 37signals, Give it five minutes:
While he was making his points on stage, I was taking an inventory of the things I didn’t agree with. And when presented with an opportunity to speak with him, I quickly pushed back at some of his ideas. I must have seemed like such an asshole.
His response changed my life. It was a simple thing. He said “Man, give it five minutes.” I asked him what he meant by that? He said, it’s fine to disagree, it’s fine to push back, it’s great to have strong opinions and beliefs, but give my ideas some time to set in before you’re sure you want to argue against them. “Five minutes” represented “think”, not react. He was totally right. I came into the discussion looking to prove something, not learn something.
There’s also a difference between asking questions and pushing back. Pushing back means you already think you know. Asking questions means you want to know. Ask more questions.
This is such a great outlook and a great way to approach the discussion of feedback for code reviews and design reviews.
It's surprising how little time development teams devote to training, or even internal discussion on effective feedback. As developers, we are constantly engaged in this kind of communication: white-boarding sessions, spec reviews, design reviews, code reviews. We're expected to give and receive feedback on a daily basis, but few of us are properly prepared for it. Not only do we lack the training, but we have many negative examples to draw from. Who hasn't been a part of a design review where tempers flare? Properly giving feedback is something that requires constant attention and practice. Receiving feedback can be just as difficult.
Culture of Communication
One of the major pillars of our engineering culture at bizo is "the 3 Cs": Communication, Communication, Communication.
We've tried hard to build a team of engineers that are eager to receive feedback, humble about their abilities, objective and gracious with their feedback, and freely giving of their own knowledge and experience. We see communication as a prerequisite for building a world-class team and developing high-quality code. You often hear the phrase "strong opinions, weakly held," and that is the kind of culture we have tried to build.
Communication is hard. It takes real team agreement and commitment to continued work to keep this culture alive and well. It's important the team views effective communication as important and that the culture supports it.
Code Reviews
Code reviews are something that can easily be approached from the wrong perspective, both as an author or reviewer.
As a reviewer, it can be easy to jump in and argue, to try and push 'your' solution (even though it may be equivalent), to push back instead of asking questions and trying to understand.
As an author, it's far too easy to get attached to your code, to your specific solution/naming/etc. It's also easy to feel like each comment is an attack on your ability, and that by accepting the feedback, this somehow means that you were wrong or did a bad job. Of course, nothing could be further from the truth!
At Bizo, we perform code reviews for every change. They are a major part of our culture of communication. In order to perform effective code reviews, it's important to have some shared guidelines that help support effective communication.
Here are some guidelines we've found to be helpful for performing code reviews:
What is a code review
- A careful line-by-line critique of code by peers
- happens in a non-threatening context
- goal is cooperation and mutual learning, not fault finding
Code reviews are a team exercise to improve understanding and make the code better!
When people think of code reviews they usually think of catching bugs. Code reviews do occasionally catch bugs or potential performance problems, but this is rare.
Just as important is fostering a shared understanding of the code and exposure to new approaches, techniques, and patterns. Seeing how your peers program is a great way to learn from them.
Ensuring coding standards and style guides is another way code reviews help. Working on a team it's important to keep readability and quality high using a shared vocabulary.
As an author
As an author, it's important to view each comment as a new opportunity to improve your code. Instead of jumping into defense mode, take a step back and think. Try to approach the code again for the first time with this new perspective. Your team has a lot of experience and varied backgrounds -- draw from them! They are there to help you. Use the gift of their experience and knowledge to improve the code.
Trust the team, and view all comments as action items. Some changes can seem arbitrary, especially when it comes to naming and organization. Unless there's a strong reason, tend to agree with your reviewers. If a reviewer finds something confusing, it is confusing! Code spends most of its life in maintenance and programming is a team sport. Remember that they are your audience, and you want them to be able to understand your code at 4am after a system crash.
As a reviewer
As a reviewer, it's important to take the time to understand the code, think, and ask questions to understand the code before providing feedback. The author probably spent a lot more time thinking about the problem and the approach over the course of the project.
Be strict on coding standard and style guide violations. The real cost of software is maintenance (80% according to Sun). It's important the code is easily understood by the team.
Be gentle on personal preferences. If it's not a standard violation and just a matter of personal preference, defer to the author. It's okay to present your perspective, but mention that it's just a preference and not meant to be taken as an action item.
Trust the author. It's often the case that there are many valid approaches to a problem. It's great to present alternative approaches and discuss pros/cons of various approaches. If you see alternative solutions, bring them up! When discussing alternatives, make sure to listen to the author. Remember they are the subject matter expert and you are working together on the same team.
It takes work!
Communication is hard! It's easy to screw-up. It's easy to go into attack or defense mode when you're passionate about what you're doing. It's really something we all need to remind ourselves to work on every day. It's something we need to periodically remind ourselves as a team. Try to view each review as an opportunity to practice these guidelines. Just remember to take a step back, think, and ask questions.