Archive

Posts Tagged ‘google’

“Error 418 (I’m a teapot)!?” – A cute Easter egg from Google

October 13, 2014 1 comment

Teapot - pre-pour
Pouring

If you develop for the web, chances are you know some of the HTTP status codes, numerical values that the server returns to the client to tell it whether its request was successful or not. Statuses in the 400 range indicate a client error; for instance 400 indicates a “Bad Request”. One of the lesser known error codes is 418. From the Wikipedia article on List of HTTP status codes:

418 I’m a teapot (RFC 2324)
This code was defined in 1998 as one of the traditional IETF April Fools’ jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol, and is not expected to be implemented by actual HTTP servers.

Well, Google likes Easter eggs and jokes more than just about any company I can think of. If you go to google.com/teapot you’ll see an adorable robot teapot, just waiting for you to tip it over and pour it out. (Click on web version, or even cooler, tip your phone on its side!)

Animated gif

Disclaimer: I work at Google but have nothing at all to do with this feature. The opinions expressed here are mine and do not necessarily reflect those of my employer

Categories: photo, video Tags: , , , ,

Go gotcha #0: Why taking the address of an iterated variable is wrong

February 25, 2014 6 comments

Golang mascot
Go mascot – by Renée French under Creative Commons Attribution-Share Alike 3.0 Unported from http://en.wikipedia.org/wiki/File:Golang.png

Disclaimer: Go is open source and developed by many Google employees. I work for Google, but the opinions expressed here are my own and do not necessarily represent that of Google.

Go is my new favorite programming language. It’s compact, garbage collected, terse, and very easy to read. There are some things that trip me up even now after I’ve been using it for awhile. Today I’m going to discuss the range construct and how it has a surprising feature that might violate your assumptions.

Range

First, the range keyword is a way to iterate through the various builtin data structures in Go. For instance,

a := map[string]int {
    "hello": 1,
    "world": 2,
}
// 2 element range gets key and value
for key, value := range a {
    fmt.Printf("key %s value %d\n", key, value)
}
// 1 element is just the key
for key := range a {
    fmt.Printf("key %s\n", key)
}

// Works for slices (think of them as vectors/lists) too
b := []string {"hello", "world"}
// 2 element range gets the index as well as the entry
for i, s := range b {
    fmt.Printf("entry %d: %s\n", i, s)
}
// 1 element gets just the index (notice the pattern?)
for i := range b {
    fmt.Printf("entry %d\n", i)
}

This outputs

key hello value 1
key world value 2
key hello
key world
entry 0: hello
entry 1: world
entry 0
entry 1

Try this code in the Go Playground

Solution search – pointers

Imagine the case where we have a struct as follows

type Solution struct {
    Name string
    Cost int
    Complete bool
}

Say that we’re doing some sort of optimization where we’re looking for the minimum cost solution that meets some criteria; for simplicity’s sake, I’ve put that as the ‘complete’ bool. It’s possible that no such Solution matches, in which case we return a nil solution.

A reasonable implementation would be as follows

func FindBestSolution(solutions []Solution) *Solution {
    var best *Solution
    for _, solution := range solutions {
        if solution.Complete {
            if best == nil || solution.Cost < best.Cost {
                best = &solution
            }
        }
    }
    return best
}

Do you see the bug? Don’t worry if you don’t – I’ve made this mistake a few times now.

Let’s add some tests to find the problem. This is an example of a table driven test, where the test cases are given as a slice of struct literals. This makes it very easy to add new test cases.

func TestFindBestSolution(t *testing.T) {
    tests := []struct {
        name      string
        solutions []Solution
        want      *Solution
    }{
        {
            name:      "Nil list",
            solutions: nil,
            want:      nil,
        },
        {
            name: "No complete solution",
            solutions: []Solution{
                {
                    Name:     "Foo",
                    Cost:     25,
                    Complete: false,
                },
            },
            want: nil,
        },
        {
            name: "Sole solution",
            solutions: []Solution{
                {
                    Name:     "Bar",
                    Cost:     12,
                    Complete: true,
                },
            },
            want: &Solution{
                Name:     "Bar",
                Cost:     12,
                Complete: true,
            },
        },
        {
            name: "Multiple complete solution",
            solutions: []Solution{
                {
                    Name:     "Foo",
                    Cost:     25,
                    Complete: false,
                },
                {
                    Name:     "Bar",
                    Cost:     12,
                    Complete: true,
                },
                {
                    Name:     "Baz",
                    Cost:     25,
                    Complete: true,
                },
            },
            want: &Solution{
                Name:     "Bar",
                Cost:     12,
                Complete: true,
            },
        },
    }
    for _, test := range tests {
        got := FindBestSolution(test.solutions)
        if got == nil && test.want != nil {
            t.Errorf("FindBestSolution(%q): got nil wanted %v", test.name, *test.want)
        } else if got != nil && test.want == nil {
            t.Errorf("FindBestSolution(%q): got %v wanted nil", test.name, *got)
        } else if got == nil && test.want == nil {
            // This is OK
        } else if *got != *test.want {
            t.Errorf("FindBestSolution(%q): got %v wanted %v", test.name, *got, *test.want)
        }
    }
}

If you run the tests you’ll find that the last test fails:

--- FAIL: TestFindBestSolution (0.00 seconds)
    prog.go:82: FindBestSolution("One complete solution"): got {Baz 25 true} wanted {Bar 12 true}
FAIL
 [process exited with non-zero status]

This is strange – it works fine in the single element case, but not with multiple values. Let’s try adding a case where the correct value is last in the list.

    {
        name: "Multiple - correct solution is last",
        solutions: []Solution{
            {
                Name:     "Baz",
                Cost:     25,
                Complete: true,
            },
            {
                Name:     "Bar",
                Cost:     12,
                Complete: true,
            },
        },
        want: &Solution{
            Name:     "Bar",
            Cost:     12,
            Complete: true,
        },
    },

Sure enough, this test passes. So somehow if the element is last the algorithm works. What’s going on?

From the go-wiki entry on Range:

When iterating over a slice or map of values, one might try this:

items := make([]map[int]int, 10)
for _, item := range items {
        item = make(map[int]int, 1) // Oops! item is only a copy of the slice element.
        item[1] = 2                 // This 'item' will be lost on the next iteration.
}

The make and assignment look like they might work, but the value property of range (stored here as item) is a copy of the value from items, not a pointer to the value in items.

This is exactly what’s happening in this case. The solution variable is getting a copy of each entry, not the entry itself. Thus when you take the address of the entry, you end up with a pointer pointing at the LAST element in the slice (since the iteration stops at that point). To illustrate:

package main

import "fmt"

func main() {
    strings := []string{"some","value"}
    for i, s := range strings {
        fmt.Printf("Element %d: %s Pointer %v\n", i, s, &s)
    }
}

Element 0: some Pointer 0x10500168
Element 1: value Pointer 0x10500168

Note that the same pointer is used in both cases. This explains why the Solution pointer ended up pointing at the last element of the slice.
Playground

So how do we work around this problem? The key is to introduce a new variable whose address it’s safe to take; its contents won’t change out from underneath you.

Broken:

if solution.Complete {
    if best == nil || solution.Cost < best.Cost {
        best = &solution
    }
}

Fixed:

if solution.Complete {
    if best == nil || solution.Cost < best.Cost {
        tmp := solution
        best = &tmp
    }
}

With this patch the tests pass:

PASS

Program exited.

Alternative design

A great feature of Go is that you can return multiple values from a single function. Here’s an alternative implementation that doesn’t suffer from the previous problem.

func FindBestSolution(solutions []Solution) (Solution, bool) {
    var best Solution
    found := false
    for _, solution := range solutions {
        if solution.Complete {
            if !found || solution.Cost < best.Cost {
                best = solution
                found = true
            }
        }
    }
    return best, found
}

Since best is copying the VALUE of the solution variable, this works correctly. You can play with this example and see how the tests change in the Playground.

This illustrates one other nice feature of Go – all types have a ‘zero’ value that is legal to use. For strings this is the empty string, for pointers it’s nil, for ints it’s 0, for structs all of types are set to zero values. The line var best Solution implicitly sets best to be the zero solution. If I wanted to I could get rid of the found bool altogether and just compare the returned solution with another zero valued Solution.

Conclusion

I introduced some basic features of Go, including maps, slices, range, structs, and functions. I provided links to the amazingly useful Go playground which lets you easily test out code, format it, and share it with others.

I showed two implementations of a function that searches through a slice of struct values, searching for a solution that meets some criteria.

The first example using pointers led to a subtle bug that’s hard to find and solve unless you know how range works. I showed how to write unit tests that exercise the function and helped flush out the bug. I also explained what the bug was and how to work around it.

Finally I showed a version of the same function that uses Go’s multiple return types to return a found boolean rather than using a nil pointer to signify that the value wasn’t found.

Chrome’s sound indicator – a welcomed innovation for lessening embarrasment

February 13, 2014 1 comment

Which tab is playing music? It's easy to tell now

I sat at my desk early in the morning while the office was mostly empty. A coworker arrived, said hello and sat down to work. She put on her headphones and started blasting music. The only problem? Her headphones were unplugged and the music was playing for the whole office to hear.

Accidental noise like this is very embarrassing. I welcome all innovations that make this less likely to occur. I was blown away when I used an iPod for the first time and unplugged the headphones. Unlike the CD players I had used before, the music paused. With the iPod it didn’t make sense to continue to play music without the headphones plugged in, since there was no internal speaker.

I am happy that both iPhone and Android adopted this convention as well. You’re much less likely to embarrass yourself if the sound stops as soon as headphones are removed rather than automatically switching over to the external speakers. I wish that laptops did the same, but alas.

I live most of my work day in a browser. I often end up with a whole slew of tabs. Suddenly I hear some sort of noise – one of the dozen pages I have open is blaring an ad. I usually have to search each tab one by one to try to find the culprit. Chrome recently launched a new feature to visually distinguish which tab is making noise. This is a brilliant innovation, and one I welcome in my quest not to make a fool out of myself in front of others.

Disclaimer: I work at Google. The opinions expressed are my own and do not represent that of my employer.

Categories: iPod, UI Tags: , , , , , ,

Book Review: Team Geek by Ben Collins-Sussman and Brian W. Fitzpatrick

August 27, 2012 1 comment

Team Geek: A Software Developer’s Guide to Working Well with Others, by Ben Collins-Sussman, Brian W. Fitzpatrick
Team Geek cover image

Disclaimers: I received a free copy of this book to review from O’Reilly. I work at Google, as do the authors, but this review reflects my views only and not necessarily those of Google.

One thing I have learned over my three years of professional software development is that you really are writing code for other people to read, not for the compiler. This dual nature of programming, the precise, exacting specifications that run on the computer, and the imprecise, ambiguous human factor, is fascinating to me. Ben Collins-Sussman and Brian W. Fitzpatrick, two of the engineers behind the SVN version control system, currently working at Google, have written Team Geek, a book that aims to impart lessons learned in creating better software through better people skills and teamwork.

Programmers tend to lionize the lone programmer, like Linus Torvalds of Linux fame. In some rare cases, geniuses do manage to accomplish incredible things on their own. But in most cases, great software is a collaborative effort performed by a team of people of varying skills, backgrounds, and communication styles. There are many books which help improve your technical proficiency, but this is one of the few I’ve encountered that addresses the importance of working effectively with teammates.

I won’t reiterate all of the content of the book but there are a few themes that occur throughout that I’d like to touch on.

The first is that it is crucial to spread the knowledge throughout the team rather than keeping it siloed in the heads of a few people. They whimsically refer to this as the “bus factor” – how many people would it take to be hit by a bus (or be otherwise incapacitated) before the project would fall apart?

One way of increasing this shared knowledge is through the use of communication channels that are easily archivable and searchable rather than through point to point communication. For instance, it is better to ask questions of the team via an IRC channel or mailing list than to ask someone directly, because that exchange can be easily found in the future. It also gives other team members visibility and input into the decision making process.

The culture of the team is also frequently discussed. In the previous example, archiving technical discussions would do no good if no one bothers to search and try to find answers by themselves prior to asking someone for the answer. The shared values of the team are crucial to its effectiveness.

Another main theme of the book is focus, or “saying no to all the distractions.” Part of an effective team, the authors say, is a manager who can shield engineers from the chaos inherent in the organization. This is a form of avoiding distractions at a high level – working on things which do not actually matter for your project. One relevant quote I’ve found in this regard is

There is nothing so useless as doing efficiently that which should not be done at all — Peter Drucker

One way the authors suggest to maintain focus is to decide on a mission statement. It might sound cheesy, but they offer a compelling argument as to its efficacy. They relate an example of how they used this technique on one of their projects and it became clear that many of the senior engineers had very different goals and ideas of what the product should do. Had they not forced the team to clearly specify what they were trying to accomplish and what the non-goals of the project were, there would have been significant wasted effort by people working at cross purposes. They use the analogy of a cart being pulled by different team members in different directions – by not working towards one goal, the cart will not move forward as quickly as it would if all were pulling together.

At a lower level, distractions abound as well. While programming, it takes significant concentration and effort to get engrossed in the task at hand and to ‘load’ the program structure into one’s head. Context switching is very bad for productivity because the cost of reloading this state is so high. Sometimes these context-switching distractions come from other team members, such as when someone interrupts to ask a question. The authors suggest that the team come up with a strategy for minimizing these disruptions, both to increase productivity and decrease frustration. For instance, in one team the authors led, any time Alice needs something from Bob, Alice would make her presence known, Bob would verbally acknowledge Bob but not stop what he was doing, finish what he was doing, and only then stop and talk to B.

While much of the book is generalizable to any sort of team environment, the authors do give some coding specific advice. There are discussions on handling code reviews effectively, dealing with people who constantly dig their heels in and criticize others’ technical solutions, and ways to avoid ego while coding.

Conclusion

I thoroughly enjoyed this book, reading it cover to cover over two legs of an international flight. Much of the advice in the book is common sense but there are also many specific, concrete ideas that I had never considered before. I would recommend this book without reservation to anyone working on a team that writes software.

Closing a subset of tabs in Google Chrome

March 5, 2012 Leave a comment

Do you use Google Chrome? Do you sometimes want to close multiple tabs at once? Here are three ways to do that, two of which are not immediately obvious.

Close Tabs to the Right

This is the standard way I’ve been using to close tabs. You right click on a tab, choose “Close Tabs to the Right”, and all tabs to the right of that tab are closed. This works well for two reasons:

  1. When you manually create a new tab, it opens on the far right
  2. When you open links in a new tab, it will open immediately to the right of the tab you’re currently in.

Thus if you have opened a few tangentially related tabs from a main article, you can click on the main article’s tabs, choose Close Tabs to the Right, and all of those newly opened tabs will go away.

Ctrl/Meta click tabs

You can add tabs to the current selection by holding control (Windows/Linux) or command (OSX) while clicking on additional tabs. This is exactly the same behavior as when you are selecting multiple files from the desktop GUI. Once you have the tabs you want to close selected, you can right click on any one of the selected tabs and choose “Close Tabs.” This approach works better than the “Close Tabs to the Right” approach when the tabs you want to close are not all next to each other.

Control click example

Why might you want to do this rather than clicking the X in each tab individually? I can think of two main reasons.

The first is that it provides you with a much larger click target for each tab. With this method, you can click almost the entire tab to add it to the selection, then right click almost the entire area of any of these tabs to bring up the context menu to close tabs. The X button itself, by contrast, has a small clickable area that requires more dexterity. (See the Wikipedia article on Fitt’s Law for more information on the relationship between accurate navigation to a UI element and the size of that UI element)

The second reason you might use this method is that it allows you to make your selections all at once before closing any one of them. If you close them one at a time, the tabs move around to take up the empty space. The Chrome team has done an amazing team with the UI design of the standard close tab functionality (e.g. the close button will always stay under your mouse cursor as the tabs reshuffle, and they only will change size once your cursor leaves the tab bar), but it might still be more intuitive to select them all at once while their location is fixed rather than finding them in the changing tab bar as each consecutive tab is closed.

See this excellent blog post by Basil Safwat for more on the Chrome tab close behavior.

Shift click tabs

Finally, you can extend the selection of tabs by shift clicking on any other tab. In other words, the currently opened tab is one endpoint of the selection, you shift click on any other tab (either to the left or right), and that becomes the other endpoint in the selection interval. Here is an illustration of the process:

Shift click example

Once you have your selection, you can right click on any of them and choose Close Tabs as mentioned earlier. This approach is best when you have a contiguous span of tabs you want to close, but there are some tabs to the right that you want to keep open.

Conclusion

I hope you found this brief foray into the ways of closing multiple tabs in Chrome as interesting. I think most Chrome users know of the Close Tabs to the Right option, but I would guess most people don’t know about about the shift click and ctrl/command click ways of selecting tabs.

Categories: Uncategorized Tags: , , , ,

Gmail Motion

April 1, 2011 Leave a comment

To send, lick a stamp and place it on your knee

Very amusing video

Categories: Uncategorized Tags: ,

Cut/Paste bug in Google Docs Spreadsheets

February 1, 2011 4 comments
Video illustrating the bug

Video illustrating the bug

I use Google Docs Spreadsheets frequently and love the ability to collaborate on the same spreadsheet with multiple people currently.  The automatic versioning is excellent as well.

There is an extremely annoying bug that plagues at least the Chrome/Firefox versions of the application running on Mac OSX 10.6.6; I am posting here with the hopes that more people up-vote my support ticket and the bug is resolved sooner.  See the full bug ticket here.

In a nutshell, the problem is that the cut keyboard shortcut (⌘X) acts differently than the cut context menu.  When you fill the cut buffer via the keyboard shortcut and paste it via the paste keyboard shortcut (⌘V), things work fine.  When you later cut a different row/cells via the Cut context menu and paste with the keyboard shortcut, the original text you cut via the ⌘X shortcut is pasted instead of the text you just chose to cut.

It’s easier to see what I’m talking about via screencast; see this video for a minimal example of how to reproduce the bug.

I’m interested if this plagues Windows users and those using different browsers.  Please post in the comments with your results.