Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Trace Wax

On asking for help

Trace Wax
Monday, May 13, 2013

Years ago in college, I took part in “The Game”: a 24-long scavenger hunt, driving all over the Bay Area, decoding clues that would lead us to the next location, each clue nerdier than the next.  If we ever got stuck, we could call Game Control and they’d help us to the next clue.  One clue was a matrix.  We figured out if we took the eigenvalues down the diagonal, it was a 10-digit phone number.  It didn’t come out right, and we spent 5 hours trying to recode and decode it.  No dice, so we finally called Game Control.  They apologized for their mistake; there was an error in the matrix, and they gave us the phone number.  It was for a bowling alley, which had just closed.  All the teams had been there a couple hours before, bowling for their next clue after having called Game Control much sooner.  Our stubbornness caused us to miss out on bowling and we had to call Game Control again to get the location of the next clue.

Fast forward to last month.  I drink a lot of water and found myself often the one who took the last drop of water from the water cooler.  So I’d fetch and hoist the 5 gallon replacement jug from down the hall, sometimes several times per week.  I could have asked for help, but had thought, why be a bother when I can do it myself?  I didn’t really mind…until I found myself with a hernia from the lifting.  A minor outpatient surgery later, things are pretty well back to normal, but there will be no more carrying of the water jugs.

Fast forward to last week.  We were deep in someone else’s code and far down a rabbit hole of investigating things we didn’t quite yet understand.  There were many avenues we could explore, and we could have kept on down that rabbit hole for a long time.  But then my hernia scar twinged.  So my pair and I got up and asked the original dev, and we were on our way in minutes.

While the thrill of solving everything alone is tempting, we pair and share a team for a reason.  And if we need anything else, we can ask an entire office of Pivots every morning in the ‘helps’ part of our daily standup.  Whether in a scavenger hunt, in transporting water, or in a sea of unfamiliar code, I’m looking forward to asking for help when I need it.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ward Penney

A SASS with Bootstrap Workflow

Ward Penney
Monday, May 13, 2013

So you’ve decided to start a project with Twitter Bootstrap, but you want to use SASS (SCSS)? Well, this is the post for you. Here are some tips from my current workflow for starting a SASS with Bootstrap project. DISCLAIMER: there many ways to slice this cake. So please, take what you like and leave what you don’t!

A Typical File Structure

In the stylesheets source folder, I generally only have one primary SASS file, that imports all others. If you are using a Rack app, do not use sprockets directives here, just SASS.

Depending on your stack, you will have some place where you have a stylesheets/ folder. Within that folder, I typically set up a basic folder structure that looks like this:

  • application.sass
    • /libraries
      • _variables.sass
      • _mixins.sass
    • /vendor
      • _bootstrap.scss
      • _bootstrap-responsive.scss
      • bootstrap/
        • _accordion.scss
        • _alerts.sass
        • _breadcrumbs.sass
        • etc…
    • /components
      • _tables.sass
      • _forms.sass
      • etc…
    • /sections
      • _homepage.sass
      • _product_detail.sass
      • _style_guide.sass
      • etc…

./libraries/: contains only variables and mixins: SASS that does not render any actual CSS, but is used later. Why? You’ll find out later!

./vendor/: Vendor framework libraries. In this case, only Bootstrap is here.

./components/: SASS patterns intended to be used across the site. Pretty much everything in here will be devoted a section in the live style guide.

./sections/: Layouts and other page-specific stylings. Anything that is not intended to be used in multiple places in a versatile way.

Bootstrap Source

I like the Bootstrap source SASS not hidden in a gem because I can want to control exactly which features are included. You don’t want to be in a situation where it feels like you can’t deprecate or evolve away from Bootstrap because you don’t control it. So, here is what I do:

  1. Go to Thomas MacDonald’s amazingly well-maintained Bootstrap port to SCSS at https://github.com/thomas-mcdonald/bootstrap-sass

  2. Copy the contents of https://github.com/thomas-mcdonald/bootstrap-sass/tree/master/vendor/assets/stylesheets to your vendor folder described above

  3. Open up the bootstrap/bootstrap.scsss and comment out NEARLY EVERYTHING. Even the grid if you want to use a different grid. Uncomment features as you need them, when your user stories demand the functionality.

  4. Include the vendor/bootstrap file in your ./style.sass file, and BOOM you’ve got a full controllable Bootstrap source.

  5. When you need buttons, uncomment buttons. When you need wells, uncomment wells. Rinse and repeat.

  6. Replicate this process for the javascript also, only including what you need when you need it.

(Note, this method also works if you don’t have Rails, or a rack app that can use gems, this still works for you. Yes, you can compile SASS with Bower and Grunt. Check out Sam Richard’s style guide prototyping stack)

Extending the Grid

With Bootstrap, you may typically insert its class selectors and elements into your markup to compose the, but some peepz do not desire this for semantic, SEO and other reasons.

SASS offers an attractive way to remove the clutter with the SASS @extend directive, however it has two performance pitfalls:

  • In Development: Using it in SASS nesting (more than two levels) may significantly slow down your compilation time, especially if that element is being @extend-ed a lot.
  • In Production, overuse can can create so many selectors on one element that it can lag the browser significantly.

In Bootstrap in particular, it becomes tricky because you have to extend the grid class, as well as the wildcard class that applies the padding. For example, a Bootstrap element classed with .span3 will receive stylings from the .span3 selector, as well as a funky selector [class*=’span’]. For example, you can’t just do this:


.advertising-sponsor
  @extend .span3

This misses the [class*='span'] wildcard selector because @extend only scours literal selectors, not searching for anything that MAY apply. Therefore, you have to do this:


.advertising-sponsor
  @extend .span3
  @extend [class*='span']

The downside is the second @extend adds an extension to that target selector every time you use it, and a really long one if it is nested. Those hit the performance issues I described above, hard.

So, my process now is to create my own mixin that allows me to quickly pseudo-extend the grid class by calling the Bootstrap mixin that prints their styling. I place the following into my ./variables/_mixins.sass:

=bs-extend-span($spanNum)
  +grid-core-span($spanNum, $gridColumnWidth, $gridGutterWidth)
  float: left
  min-height: 1px
  margin-left: $gridGutterWidth

This essentially renders what bootstrap does for it’s span classes. This does duplicate CSS in the compiled result, but I have found that the performance impact of downloading more CSS pales in comparison to the pains suffered by @extend in development time, or in a more severe case, crashing or lagging the users’ browser.

Styling Bootstrap with Variables

Take a look at the ./vendor/bootstrap/_variables.sass. Notice how all the variables have !default after them? That means that SASS will NOT overwrite this variable if it is already defined. This allows you to create your own ./libraries/_variables.sass file, and include it in the load order before Bootstrap and effectively control those variables. This will be your primary way to style Bootstrap colors and such.

Using Compass or Bourbon with Bootstrap

Some people prefer Compass’ mixins. Some people like Bootstrap’s. Some like Bourbon’s. IMO, they are all good and I don’t mind using any, but it is a good idea to commit to one. For example, Bootstrap’s =Opacity() mixin takes a value from 0-100, while Compass’ function takes a value from 0-1. There is a variable order conflict with =transition(). I sometimes import pieces of compass, instead of the whole thing. For example, I like the ever-handy Compass =experimental() function. You can choose to import only specific files from Compass:

@import compass/css3/shared

Conclusion and Upcoming Topics

That’s it for now! Let me know if you have any topics you want me to expand on, or ideas for posts you want to see. I am currently doing a style guide using Groundwork-CSS, and hope to do a similar post later! Follow me on twitter for various nonsensical ramblings.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Graham Siener

Storyation Workshop: How to get business stakeholders to create stories

Graham Siener
Monday, May 13, 2013

I read Lean From the Trenches last weekend and it was great.  Not because it provided black and white protocols for running an agile product development team, but rather because it showed how a real team operates under real conditions.

I want to focus this post on a quote from the book:

The definition of “ready for development” can be achieved only if all specialties work together to estimate features, break them into small enough deliverables without losing too much customer value, and to agree on acceptance tests.

Ready for development is an interesting concept — it implies that every business stakeholder that has input knows what the product owner needs to ensure a developer can deliver an acceptable story.  In my experience, this is usually not the case once a product is out in the marketplace and people from non-product teams (marketing, support, executives) have specific product needs.  This could look like promo code tracking to support a marketing campaign, or a data export to support your “data science” team.  Without a good process for getting these stories into the backlog, the result is an unhealthy IPM where the PM and developers have to divine what exactly the intent of a story is.

At one of my last companies, we had this problem in spades.  Even after introducing a Pre-IPM meeting, we still felt like the quality of the stories we presented to developers in IPM didn’t represent the time we had spent discussing them.  To add insult to injury, getting the story requester to accept a delivered story was like pulling teeth.  Once we did sit them down to walk through a story, rejection was often the result!

After reflection (and seeing this come up as a theme in several retros) we created a new weekly meeting called “Storyation Workshop.”  This session felt a lot like office hours, and we made clear the intent to only let high-quality stories into the backlog.  We (PM and Tech Lead) would do our best to interpret the needs for a feature and turn it into actionable stories.  We would also break out the necessary pieces from the nice-to-haves.  Make no mistake, though — the business owners were on the hook to bring justification for a feature and if it didn’t pass muster it lived in the Icebox for another sprint.

We were fortunate (as a company) to have support for keeping a healthy backlog and not jumping stories in the priority queue.  I saw many benefits to this new process:

  • All the other teams — marketing, professional services, customer support, data science — paid closer attention in IPMs and made sure that their needs were well represented
  • Acceptance happened more quickly after a story was delivered, and expectation alignment meant rejections went way down
  • Everyone got better at story writing as they started to grok how we broke down features and the logic behind it
  • More greenfield thinking popped up and made it into the backlog as actionable work

The first three were proof to me that we were missing a critical process in the arc of a story.  The last bullet (greenfield thinking) was a pleasant surprise.  It turned out that people were afraid of bringing a half-baked idea to IPM (rightfully so) but didn’t feel like they had the right forum to finish baking an idea.

Maybe this all sounds like common sense; if that’s the case congrats on having a healthy product development process!  For anyone struggling to deal with symptoms like these I suggest you try introducing a safe space for new ideas to come to light.  A Storyation Workshop could come in many forms, but you’ll know it’s working when you see more buy in from non-product team stakeholders and a faster cycle-team for their stories through the backlog.

As always, I’d love to hear if you’ve incorporated a similar technique into your agile product development process.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Jonathan Berger

7 Best Practices for Facilitating Agile Retrospectives

Jonathan Berger
Monday, May 13, 2013

Facilitating a retro is a very powerful role; it’s almost akin to being a courthouse judge (and stenographer). By asking questions, recording testimony, and shaping the debate, you mold and influence your teammates’ feedback in a very vulnerable and trusting space. If the Product team sets goals (like a Legislature) and Development and Design teams implement them (like an Executive Branch), a retro is a chance to reflect, interpret, and set future direction—not unlike a Judiciary. In practice, that means it’s important to be especially honest and impartial, and to double-check that you’re doing justice to the team’s best interest and the speakers’ intent. Here’re a few patterns I’ve observed that help make the difference between a good retro and a bad one.

1. Explain and Enforce format

At the beginning of a retro, take a minute to explain what’s going on—even for a seasoned team, but especially for a team with new members. “We’re here to reflect and improve on process—this is a safe space, and we’re oriented towards exposing issues and taking action.” If the team isn’t explicitly aligned on why they’re in the room, they can’t get the job done. Speaking up is high value (it ensures the retro is properly oriented) and low-risk (it only takes a minute).

2. Write Everything Down Verbatim

A retro is about listening. Whoever takes notes ought to be respectful of the speakers voice. That means recording their thoughts as faithfully as possible, without interjecting opinion or commentary. If you do need to paraphrase for brevity, be as faithful to the original comment as possible—don’t insert your view, you’ll get your own turn—and confirm that your version does justice to the original. “You said ‘INSERT COMMENT HERE’ and I wrote ‘INSERT PARAPHRASE HERE’. Is that right? “

3. Categorize carefully

If you choose to categorize items, be very conservative about pre-judging what it is you’re talking about. Sure, you’ve spent the last 25 minutes talking about a few categories, but don’t jump to putting names on the buckets—that’s prejudice, and it shapes opinions. Group like items (“Are these two frownies related?”), branch out from there, and labels will emerge. Be careful that the buckets aren’t too broad to be useful; it can be tempting to draw connections among almost everything, but ideally you’ll be slicing things a little thinner, facilitating more focused action items.

4. Action Items Should Have Intent

Unclear Action Items are worse than useless. One trick is to ensure a verb is the first word of every Action Item. By definition, every action includes a verb, but sometimes the verb is glossed-over or shorthanded in the retro. Everyone in the room understands what’s meant, but afterwards that may no longer be the case. Make sure that Action Items remain actionable when viewed later.

5. Action Items Should Be Falsifiable

Be sure to frame Action Items in terms that can be assessed as “done” or not. “Refactor more” isn’t useful a useful task, because there’s no way to meaningfully tell whether it’s done. “Improve the User model’s Code Climate grade from an F to a D” is actionable, and lets the team take small, achievable steps towards improvement. Also: use Code Climate, Errplane, New Relic, Airbrake or other instrumentation services to help put objective measures on code quality, performance, etc.

6. Action Items Need a Single Responsible Party

Not two people. Not “team” or “all”. One person. When an action item involves the whole team, find a volunteer to be the cop and enforce compliance. If one person isn’t responsible, then no one’s responsible. Addendum: review Action Items. Print them up and put them on the team stand-up board. Cross them off as completed. Review the list at the next retro.

7. What Happens In Retro, Stays In Retro

The retro should be a safe place. Active members of the team should the be ones in the room; sometimes it’s helpful to include stakeholders that aren’t present for most of the week (but that’s a judgement call). Action Items may be displayed publicly, but it’s preferable to only share the raw notes with the people present.

These practices aren’t laws chiseled in stone; they’re hacks and ideas borne of observations of patterns and anti-patterns witnessed in many, many retros. Do you agree? Disagree? Have juicy, anonymized stories supporting or contradicting? Let us know (and share your best retro stories) in the comments.

 

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Nina Mehta

What in-house design taught me about consulting (Part 1)

Nina Mehta
Monday, May 13, 2013

In the design world, a river runs between the consultants and in-house designers.

I’ve worked at big start-ups, small start-ups, corporations, newspapers, non-profits and universities, and I have hired consultants myself. Having been on the other side, each job unique with its own challenges and joys, set me up to be an empathetic consultant.

Here’s what I believe all those years in-house taught me about consulting:

  1. Preparing for a consultant is hard
    Companies hire consultants when they’re short on time, ideas or people. And for those reasons, it can be hard for a company to get all their ducks in a row. This doesn’t mean they don’t care or can’t prioritize the project. In fact, usually it’s the opposite.

    Working in-house can mean running multiple (probably too many) projects in parallel, staying ahead of competitors, putting out fires, explaining why someone’s something got de-prioritized and all the other stuff that needs to get done, somehow. So, the companies hire a consultant, someone who can focus on one slice of the pie.

    Because the client is short on resources (time, energy, expertise), consultants end up having questions they didn’t even know they should be considering. After this, clients can be left looking and feeling unprepared and disinterested.

    Because our team was often short on time, money, ideas, people or resources, it made preparing for a consultant quite hard.

  2. This product, whatever it is, is the most important thing in the world
    For a consultant, projects come, projects go. But, for in-house designers, no project is ever done. Everything is an iteration and there’s always an opportunity, somewhere in the distance, to return to a project for another version.

    For many companies, especially young ones, that company and its product are the whole world – its bread and butter. They are out to change the world, to make it better. They have high hopes for massive adoption and high traffic, whether it be an overnight success or a slow and steady climb.

    A consultant doesn’t need to agree with the client’s world vision, but it is good to know the ingredients of their powdered Kool-Aid mix. It’s valuable to understand how and why this company, making this product, whatever it is, believes it is the most important thing in the world.

  3. User experience exists beyond the product
    As an in-house designer, I had the luxury to build on what I learned about the product and our users from project to project. Unlike consulting work, there is no starting from zero. Every project further deepens the understanding and relationship to how their customers, clients, users and site visitors think, make, explore, click, feel and tweet. The longer an in-house designer works for one company, the richer their understanding of how the product works and what an experience is like for their customers.

    An in-house designer learns from the sales, marketing and support teams, who can help guide a more holistic view of the wants, needs and desires of the users. Being this kind of designer helped me become better at knowing what questions to ask and when I can skip ahead to the nitty-gritty details. Working in-house taught me to see the nuances of user experience beyond product and interaction design.

  4. Consultants can be the bad guy
    Companies want to do things in house. Consultants are expensive, time consuming and can make the in-house team feel like they’re not good (fast, smart, creative) enough. Even for the most pragmatic creative (designer or developer), at the core, I’ve seen my teammates feel demoralized or defeated by needing to hire someone to do their job. Working in-house taught me, no matter how skilled and personable the consultant, sometimes the consultant is the bad guy.

  5. Clients are tough cookies
    In-house designers have clients, too. And they’re tough. Users? Oh yes, of course. I must mean those needy users always emailing, tweeting, wanting needing something. No! Those people are wonderful.

    In-house designers also have in-house clients – sales, marketing, recruiting, investors, designers, and developers.

    An in-house designer needs to weigh the needs and priorities of all the stakeholders – those shouting and those being spoken over – and make good judgements, arguments and compromises. And, when whatever project was done (the one that’s the most important project in the world), all those stakeholders were still my coworkers the next day. Those clients, they’re tough cookies.

I’ve been at at Pivotal Labs for only a week, so keep your oranges peeled for Part 2. In a few months, I’ll follow up on these initial thoughts and share new findings.

 

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Andrew Bruce

Smelling with your ears: TDD techniques to influence your design

Andrew Bruce
Sunday, May 12, 2013

Test Driven Development can be a hard sell. The first pitch is often designed to entice the buyer with safety features, like:

  • “How will you ensure that those bugs don’t creep back in?”
  • “Wouldn’t it be nice to know that one change doesn’t break another?”

In conversations between practiced test drivers, though, design topics tend to pop up:

  • “What is this test telling us about the design of our code?”
  • “Why is this test boring to write?”
  • “Why is this test so slow?”

Then there are really exciting questions, when getting close to a design breakthrough, like:

  • “Is this test telling us we’re lacking polymorphism in our design?”
  • “I’m tired of constructing this thing. How can we group this set of arguments into an object with a name?”

One distinguishing factor between these types of questions is the level of trust in TDD. Someone with little trust might be predisposed to abandon testing before implementation, instead choosing to test afterwards, or not at all. To such a person yet to be sold on the benefits of TDD, the safety questions make more immediate sense, while design questions are often met with blank stares. However, the safety concerns are easily brushed off: it’s a prototype. My team is so smart we don’t need tests. We need to move fast, so we’ll worry about tests later.

Explaining the basic advantages of TDD doesn’t always work as a sales pitch, because those explanations don’t reveal why testing can be difficult, much less why testing sometimes ought to be difficult. Take someone who has never let the design of their code be influenced by tests: they dislike testing for being difficult or boring. Encountering resistance in the TDD process, they choose to forgo the safety advantages of testing, and the design advantages haven’t been made clear.

As you may have gathered, I’m more excited by the design aspect of TDD and related tools than by the safety aspect. I’d like to think that if we sold how TDD can improve the design of code that’s yet to be written, we’d have an easier time tricking our friends into writing code with regression protection.

Learning to listen

There is much talk about “listening to the tests” among TDD practitioners. The listening analogy is apt. Like listening with our ears, the ability to understand what a test tells us about code quality can improve with practice. It’s a subtle concept to grasp, and one I frequently find is not well understood by otherwise experienced developers. This is unfortunate, because it’s a crucial part of getting rapid feedback on the quality of production code. By quality, I’m referring primarily to the ability to cope with changing requirements, as opposed to good coverage of features and edge-cases.

If you can’t hear what your tests are trying to say, there are tools for cranking up the volume. Below are a couple of my favorites. They’re not intended as hard-and-fast rules, but as exercises to try out when you’re frustrated with a test or wondering why it’s getting difficult to test something.

If you haven’t already, you should read about known test smells and their solutions, because we can apparently smell with our TDD ears.

Use your testing framework’s convenience helpers sparingly

In the RSpec world, this often comes down to writing readable examples without using ‘subject’, ‘let’ or ‘before’. It turns out that straightforward assignment is usually OK.

As this Thoughtbot post argues, the let helper effectively introduces Mystery Guests (implicit, hidden fixtures), and overuse results in slow and fragile tests.

I like to avoid lets, subjects and other test helpers for another reason: if I can’t stand to repeat myself in examples, I think about how the code that uses my code will feel. A boring, repetitive test setup might be telling me that my code has too many dependencies. If I’m frantically stuffing things into the database and stubbing out web service requests just to allow myself to construct an object, perhaps the object’s scope is too broad.

If you come across a test that is apparently repetitive, consider tidying the implementation of the system under test before the test itself. You may find that the noise in the test can be dramatically reduced with some production code tweaks.

Avoid stubbing methods to return values

I owe this one to Greg Moeck, who introduced something like it at the San Francisco eXtreme Tuesday Club.

First, a reminder of the definition of stubs versus mocks (to paraphrase Gerard Meszaros):

  1. A stub is a test double that allows you to control the indirect inputs of the system under test.
  2. A mock is a test double that allows you to test the indirect outputs of the system under test.

If you return a value from a stubbed method, you force your production code to depend on a blocking, synchronous call. If you could otherwise send a message and not expect an immediate response, you permit your design to (now or in the future) be asynchronous.

Further to that, if you instead use a mock to expect an output to the collaborator you were previously stubbing, you can more cleanly divide your testing into inputs and outputs of the system under test. It’s the difference between:

it "ensures user is authentic before performing the action" do
  user = stub('user')
  authenticator = stub('authenticator')
  authenticator.stub(:authentic_user?).with(user) { true }
  action = Action.new(user)
  action.perform
  expect(action).to be_complete
end

and:

it "ensures the user is authentic when action is requested" do
  user = stub('user')
  authenticator = mock('authenticator') # assume the player of this role knows who to tell when authentication succeeds or fails
  authenticator.should_receive(:authenticate_user).with(user)
  action = Action.new(user)
  action.perform
end

it "performs an action once a user has been authenticated" do
  action = Action.new(stub('unauthenticated user'))
  authenticated_user = stub('user')
  action.user_successfully_authenticated(user)
  expect(action).to be_complete
end

The code that passes the second set of examples is in better shape for when you need to queue requests to the authenticator and complete the action asynchronously. It uses a “tell, don’t ask” style. The fact that an explicit message is sent to the system under test (‘user_successfully_authenticated’) makes it clear to the reader that the request for authentication and the triggering of the action are separate bits of work. It’s someone else’s business whether I get told about the successful authentication, and how many steps are taken before I’m told.

There are several more techniques I’d like to tell you about, but this post is getting a bit long in the tooth. Maybe next time. Happy listening!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Jared Carroll

File Management in RubyMine

Jared Carroll
Sunday, May 12, 2013

As developers, we create, update, and delete files all day long. Managing files from the command-line is one of the first skills we learned. However, constantly switching from your editor to the command-line to execute a simple file command, a command you’ve probably executed thousands of times before, is tedious and slow. Instead, stay in your editor, and let it take care of the boring stuff. In this post, we’ll look at RubyMine’s file commands on OS X.

Creating Files

To create a new file or directory, press control + alt/option + N within the editor or Project tool window.

new in current directory dialog

Copying Files

Use F5 within the editor or Project tool window to copy the current file.

copy dialog

F5 can also be used in the Project tool window to copy directories.

Cloning Files

To create a copy of a file or directory in the current directory, press shift + F5.

clone dialog

Moving Files

Move files and directories with F6.

move dialog

Like the previous file commands, this command works both within the editor and Project tool window.

Renaming Files

Files and directories can be renamed in the Project tool window with shift + F6.

rename dialog

Deleting Files

Delete files and directories in the Project tool window with delete.

safe delete dialog

Locating Files

To locate a file in the Project tool window, press alt/option + F1 in the editor, and then select the Project View option, the default option, from the Select Target dialog.

select target dialog

Select Reveal in Finder to open the file in a new OS X Finder window.

Working with File Paths

Use command + alt/option + F12 to view the complete file path.

file path dialog

Selecting a directory will open the directory in a new OS X Finder window.

Copy the current file path to the clipboard with command + shift + C. Copy a reference, the current relative file path and line with command + alt/option + shift + C.

paste from history dialog

These commands are useful for when you need to work with a file on the command-line.

Relying on Abstractions

A common developer fear is that overreliance on a particular IDE’s features will cause you to forget, or maybe never learn, the underlying commands. I agree that in some cases, e.g., version control, it’s important to know what’s going on under the hood. However, these situations are rare. And when it comes to everyday commands, I’d much rather use higher-level abstractions to free me from the mundane.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Will Read

Releasing When It’s Ugly

Will Read
Saturday, May 11, 2013

This is yet another post where the tl;dr is “SHIP IT!” but with a Pivotal perspective. It can be easy to hold back an initial launch, especially when you’re trying to attract customers, not offend them. I submit that with the right tools, you can not only minimize the impact of releasing early, but create customer delight from the pain whereas perfection out of the gates would have produced none.

If your software can enable users to do the core thing you want, no matter how tangled the experience is, you should ship today under one condition: You must be able to ship again tomorrow, and the next day, and then two hours after that, and then the following Friday. In his post, 1.0 is the Loneliest Number, Matt Mullenweg talks about how that first hurdle is a big psychological barrier. He speculates that Apple employees were embarrassed at the known shortcomings of the first iPod, anxious to get a better version out before the first one even shipped. A conversation I had with my own PM was reminiscent of this. He, along with myself and the rest of the team, has a lot of pride in his work, and this project in particular. Understandably, he wants the first user to have the best experience possible. And while I agree that I want the user to be happy, I know that his experience could always be improved.

You could rephrase this idea to the proverb, “Perfect is the enemy of good.”, meaning that you shouldn’t let perfection get in the way of doing good things. Another quote, said by one of our team members struck true form most of us: “If you waited until it was perfect, you waited too long.” But I think the thought that really bring it home for me is this, “Would you rather they have an imperfect experience now, or that they have no experience at all?” I like this because if the user has an experience, the user learns something about you, and if you’re lucky (or directed through user testing), the user gives you feedback and you learn something too.

When you learn something, you can take action on it. Before that learning happens, you’re just guessing, shooting wildly in the air hoping to hit something. Delivering perfection on the first try must be near impossible with this method. Thus, like all things Pivotal, we do what we can to shorten the feedback loop – getting feedback, making a decision to act, and delivering must take as little time as possible. To do that in software, that means a few things.

First, priorities must be flexible. If something important comes along, you shouldn’t have to wait six months to get it in the next release, and you shouldn’t have to worry about the implications of  scuttling the sprint. We do this using our own tool, Pivotal Tracker which lets you easily drag the most important story to the top of the work queue.

Second, you must be able to respond quickly. If Joe is the only one who knows that code and he’s got six other high priority things to do today, you’re out of luck. That’s why we pair program and rotate, so that anyone on the team can pick up the next story that needs attention and everyone is familiar with all parts of the codebase that the team is responsible for.

Lastly, you need to be able to ship fast. There’re can’t be a two day release process on a thirty minute code change that only happens on Tuesday’s and Thursdays. It has to ship as close to now as possible, otherwise you’re wasting value by letting it sit on your virtual shelf. At Pivotal, we are always ready to ship because we don’t know any other way, our stories need reviewing, and that usually means shipping to some sort of prod-like environment, so we have to ship multiple times a day to keep the story feedback cycle small. If this process were anything other than dead simple, we’d need a pair on deployment full time just to keep up. Often times we configure our CI server to automatically deploy upon successful test runs, or in the worst case make it a manual one-click to deploy. The same technique is readily applied to production too. From there it’s up to the team to minimize downtime during deployments using whatever strategy is appropriate for the application.

But how does all this create customer delight from strife you ask? Picture the last time you withdrew cash from an ATM. You put your card in, punched some numbers, and hopefully the right amount of cash spits out. How would you rate that experience from these three choices? A) Meets Expectations, B) Excedes Expectations, C) Below Expectations. I’m guessing you didn’t get wowed by the ATM unless this was your first time taking cash out. It probably wasn’t below expectations since you got what you wanted. Rather, it was just a ho-hum experience.

What if instead, you put your card in, punch some numbers, and it buzzes for a while and shows you your receipt, but never gives you the expected cash money? Now you’re pissed. You wanted to use this service and it let you down. You really want cash, so you call the bank, planning to give them some strongly worded feedback. However you find yourself completely disarmed because the person on the other end of the line is really listening to you, not reading a script, and they quickly identify the problem, add back the money to your account, and tell you that they’re sending out a technician to fix the machine so that you and future customers have a much better experience in the future. WOW! I bet you’re thinking, “I would love to have a bank like that!” By shipping software that works in many cases, but has a compelling story to turn failures in to successes, you create a loyalty that’s a much better engine for your company than “Yeah, it meets my expectations.” Let them see you fix things. Let the users feel empowered to tell you what needs the most attention.

In the end, if you feel like you could ship, you should ship and feel good about it. You’re putting a valuable product in the hands of the users you want to help sooner. And if you’re doing it the Pivotal way, you can address their pain points quickly to change customer dissatisfaction into customer delight while being directed about how you spend your time and resources.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Luan Santos

Winning a Rumble

Luan Santos
Saturday, May 11, 2013

Last year before I joined Pivotal Labs me and my friend Raphael Costa participated in a brazilian Rumble, inspired by Rails Rumble ran by the folks from Startup DEV. It was a very interesting experience and I learned a lot from it. We won first prize, and I want to tell how we did that, and why I would change some things if it was a real project supposed to live more than 48 hours.

First, if you don’t know what a rumble is, a rumble is a developer’s competition where you have a very limited time to develop an app, your result is evaluated by some folks and the best app (according to their criteria) wins. In the case of Rails Rumble or Startup DEV rumble we had 48 hours over a weekend.

The plan

The plan can and should be draw before you start the rumble. When the clock starts ticking you have to laser focus in implementing everything you can.

First thing you need is an idea, it doesn’t need to be revolutionary it just needs to be implementable and easy. If it’s revolutionary, bonus points for you. Once you have an idea you have to describe in detail what is the featureset you are looking for.

When you have you featureset, you have to remove everything, EVERYTHING that is not absolutely required for your MVP, sort the features you removed in nice-to-have order in case you have spare time at the end.

Draw your mockups on paper and have them ready and attached to each story you selected as part of your MVP, if you have a designer, great, make him draw more detailed wireframes, if you don’t then you’ll have to use the tools the world provide you, such as bootstrap or foundation or whatever you prefer, do not waste time in things you are not expert in.

Split tasks based on capacity, in our team we were two developers, I had more experience with dev-ops (and we had to deploy our app to a VPS that was provided by the organization) he had more experience with UI/UX design, so I barely thought about how the app should look, and he barely used ssh.

Applying the plan

The basic procedure is: pick a story, assign it to you, implement it as quick and simple as you can, deliver it asap, move on.

Stay in sync, you have to know what’s happening with the other folks in your team, if your team is larger than 2, it gets more and more dangerous. You do not want to spend time resolving complicated merge conflicts so make sure the tasks are well parallelizable and that no one is stepping in no one’s toes. We had quick check-in (2 minutes, standup style) every 2 hours.

We knew what we were capable of, so we didn’t try to do anything other than that. If you never implemented a payment gateway, don’t try to do so in a 48 hour project, you will waste time and you won’t be able to finish. We knew how to TDD and we had paired before, but these were things that we were not used to do, processes not clear in our minds, we would have to learn it on the go and we would fail if we tried. When you try something new you will certainly spend time figuring things out. So because of that we didn’t even try, we did not test, we did not pair.

Commit often, commit every time, on every change. This avoids complicated merge conflicts and saves you a lot of times. Write decent SHORT commit messages so you team can understand what is that that you did just by parsing the message quickly. Pull often, see the log, git log --graph --oneline was the command we used to quickly parse messages, alias it to something simple, like gl, for example. Once you finish a feature, deploy it. Make sure everything works properly in your deployed environment.

We finished everything and more with about 2 hours to spare, in this 2 hours we looked for bugs, found some and fixed them. This spare time is essential specially if you are not TDDing, you will find problems.

What would I do differently

First of all, if you want your app to continue after the 48 hours you have to TDD, on the next day after the competition we looked at the code and it was only OK, it wasn’t bad or anything, but it was very hard to trust it and make changes because without any tests you have no confidence on doing it. The solution for us would be rewrite the app TDDing or backfill, and backfilling is very painful.

Skiping the tests is very risky, you may break everything without knowing, and that would make you fail, we took that risk and it worked for us. I wouldn’t do that again, I would TDD next time even if that means reducing the scope even more, it’s too hard to develop a real app without it.

Pair programming and TDD are things that make you very productive on the longer run, on a 48 hour crazy competition it might not be the best thing to do if you’re there to win and your team is only composed of two people. If you have a really small and simple featureset and your team has experience you can get away without it and it would be faster on this 48 hour streak. It is very likely that you will have to rewrite your app after tho.

I would pair if I had a team of 4, a single pair may not be the best for a 48 hour thing, you kinda need the parallelism on this short project. The ideal setup would be two pairs tho. More than 2 parallel developer stations would probably be a bad thing.

In conclusion

Participating is fun, we had a lot of fun, there were several good projects on the competition and it was awesome. If you ever have the opportunity to participate in one of these you should, it’s very tiring but it is worth it at least once. If you’re interested our project is still online at agrupe.se (it’s in portuguese, sorry, google translate).

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Matthew Parker

AwesomeResource

Matthew Parker
Friday, May 10, 2013

I’ve had it. I’ve had the misfortune to need ActiveResource (an http client library for giving you an ActiveRecord-like API for interacting with restful services) off and on for several years now. Even when it’s worked, it’s never worked well.

Let’s start with the way you configure it. You know how you can use a database.yml file to specify your ActiveRecord connections for different environments? Wouldn’t you expect ActiveResource to work similarly? I mean, it seems unlikely that you’d actually connect to the exact same server endpoint in test, development, and production, right? Too bad. ActiveResource gives you a single way to set a model’s “site”: an attr_writer on the model’s singleton:


class MyModel < ActiveResource::Base
  self.site = ‘http://some-server.com’
end

That global state isn’t a good sign. Even after you hack in your own environment-specific connection code, do you think your model will be thread-safe? Hell no they won’t. If you try to use your models in a threaded environment (e.g., in threaded background worker systems like Sidekiq), you’ll eventually run into a race condition on the model’s singleton “connection” attribute. And your code will raise an exception. Fun.

Let’s talk about JSON. Everyone loves JSON, right? ActiveResource is an old library; when it was originally written, XML was in vogue. The ActiveResource XML support is very mature. It’s JSON support? Broken. That’s right, it’s broken. Has been for years. Sending nested attributes over JSON does the wrong thing. There’s a fix that was merged in a year ago that will be released with Rails 4. In the meantime you can use my “activeresource_json_patch” gem.

Let’s look at the ActiveResource code. It’s a great example of Stunt Programming. Once, when attempting to determine how I might monkey-patch ActiveResource to allow me to set a lambda as the “site”, I stumbled into this method:


      def prefix_source
        prefix
        prefix_source
      end

Um, what? How could that possibly work? It’s INFINITELY RECURSIVE ISN’T IT? Let’s look in the prefix method:


      def prefix(options={})
        default = site.path
        default << '/' unless default[-1..-1] == '/'
        # generate the actual method based on the current site path
        self.prefix = default
        prefix(options)
      end

Wait, the prefix method calls itself too! It’s also INFINITELY RECURSIVE TOO!!! What’s going on? Let’s look one level deeper: the `prefix=` method:


def prefix=(value = '/')
  # snip...
  silence_warnings do
    # Redefine the new methods.
    instance_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1            
      def prefix_source() "#{value}" end            
      def prefix(options={}) "#{prefix_call}" end          
    RUBY_EVAL         
  end       

rescue Exception => e
  logger.error "Couldn't set prefix: #{e}\n  #{code}" if logger
  raise
end

And there you have it. The prefix= method redefines the prefix_source and prefix methods. Thereby avoiding the infinite recursion. FACEPALM

All right, enough complaining. Taken at face value, ActiveResource isn’t actually all that bad. If your needs are incredibly simple, it will likely do the job. And I’ve actually tried to improve the ActiveResource ecosystem over the years. I released a gem that dealt with the nested-attributes-over-JSON bug during the interim until the bug fix is released. I created another gem that made environment-specific site configurations possible. But in the end, I’ve just had it. The code’s a mess. The library is half-forgotten. It’s time for a reboot.

While I was at home recovering from the latest round of the never-ending biological warfare called being a parent, I started a new project on Github: AwesomeResource (http://github.com/moonmaster9000/awesome_resource). Some goals:

  • ActiveRecord-like API
  • Thread-safety
  • Environment-specific configuration
  • Dynamic site, proxy, and password configuration (instead of forcing them to be statically configured in the code)
  • First-class JSON support
  • An integration test suite that would verify that something as critical as JSON support will actually work against a live Rails app
  • A spec that exposes the JSON format the AwesomeResource expects from a server

I’ve got a single feature for SomeModel.create passing. It’s a start.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (781)
  • rails (113)
  • testing (88)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (55)
  • techtalk (44)
  • rspec (38)
  • ironblogger (32)
  • productivity (30)
  • activerecord (29)
  • gogaruco (29)
  • git (28)
  • nyc (27)
  • rubymine (26)
  • bloggerdome (23)
  • mobile (22)
  • process (21)
  • pivotal tracker (21)
  • cucumber (20)
  • design (19)
  • jasmine (19)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • tracker ecosystem (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • bdd (14)
  • gem (13)
  • css (13)
  • tdd (13)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to Labs Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. ...
  10. 124
  11. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >