Shared posts

24 Dec 19:47

trust, but verify …

by derickbailey

My dad was recently involved in a very large project, working as the project manager. It was a construction project with a handful of contracting companies that he had worked with in the past. One of the crews, though, decided they wanted to get lazy on the job and did about an hour worth of work in about 5 hours, one day.

surveilance-coding

The real issue was that this was the first day on the job for this crew – there was no history of good work on this job site, and immediately obvious reason why it was taking so long. So my dad called their manager and talked to him about what was happening – very friendly, offering the manager opportunity to explain, and wanting to find a reason why this was ok for the first day.

A few days later, my dad was walking with one of his project leads and passed through the area where this team was working. One of the crew members looked up and said “coming to check up on us?” with a grin on his face. My dad stood silent for a moment, while his project lead said “why? do I need to?” The construction worker immediately became aware of himself and tried to back out of the conversation, awkwardly saying “well, no. Of course not!”

That crew never had any issues afterward – they did great work, got it done on time, and built a professional relationship with my dad and the other project leads.

Trust The Team

I have to admit, I would not have been quite so astute in my response if I were the project lead. I probably would have blurted out, “Yes.” with a very serious tone of voice, had I been asked if I were checking up on the crew. But that’s not the kind of thing that I really want to do, and I certainly wouldn’t want a project manager to do that to me. It creates an air of distrust, as if you were spying on people with cameras and accusing them of not working, constantly.

No one wants to work in an environment like that. We need freedome, flexibility, autonomy and independence to do our jobs – the same as the construction crew needed.

Now, this doesn’t mean that my dad never checked the work they did. There are a lot of regulations that have to be met, a lot of plans that need to be accounted for, and a lot of safety issues that need to be addressed when doing commercial construction. It was absolutely necessary to verify the work, just as it is necessary to verify the software we build before shipping to customers. That doesn’t mean there is no trust. It only means that we recognize human fallibility and the need to verify work, in spite of the trust that we place in people.

Trust, But Verify

There’s a saying that I learned a long time ago from some ex-military friends and co-workers: trust, but verify. The idea is simple. You default to trusting someone for whatever it is… work or otherwise. But that doesn’t mean you have to be blind and wreckless with your trust. It’s ok to verify the information provided. In fact, it’s usually a good idea. No one is perfect. Mistakes are made. It happens.

But when mistakes are made, we only need to educate and correct the mistake. If we trust the person that made the mistake, we can help them learn and they will improve.

Trust vs Assistance

It’s also important to understand the difference between blind trust and assistance.

I once assigned a team member some work that I knew was just beyond their current ability. I did this to help them stretch and grow. But I made a mistake and blindly let them go at it for nearly 6 weeks. Sure, I asked for updates on progress but I never once offered to do a design or code review, and I left it up to them to ask questions and seek help. The results were … a mistake. I squarely blamed myself in the retrospective for the work he did. I knew I should have spent more time offering assistance, and helping him to grow in to the design skill that I wanted him to reach.

My desire to trust, blindly, created a lost opportunity for someone to grow faster and ended up costing a lot of time and money for the project.

Trust, Assist, and always Verify

There are two extremes, here: absolute trust, and never trusting. A great leader will understand how far to lean toward either end of this spectrum, in nearly any situation. That doesn’t mean mistakes won’t be made, but that they will be caught early and corrected.

Default to a high level of trust, in your team and your coworkers. Assist when someone is having a hard time or is given a task that they must grow in to. And always verify the work they do, to ensure it will perform as needed.

- Derick

13 Oct 19:54

Writing Vim Syntax Plugins

by Keith Smiley

One of Vim’s most powerful features is the vast built-in and available language support. With the rise of new languages and the desire to write them in Vim with proper syntax highlighting, it’s useful to understand how to create our own syntax plugins for Vim in order to write, extend, or contribute to open source syntax plugins.

Syntax Plugin Structure

Syntax plugins, like all Vim plugins, follow a basic folder structure. This file structure became mainstream with the release of pathogen and works with all modern Vim plugin managers such as Vundle and vim-plug. I’m going to be using swift.vim as an example of how syntax plugins fit together. Here is the relevant file structure (using tree):

├── ftdetect
│   └── swift.vim
├── ftplugin
│   └── swift.vim
├── syntax
│   └── swift.vim
└── indent
    └── swift.vim

ftdetect

The first configuration file we encounter is in the ftdetect folder (:help ftdetect). In this folder we have one or more files named after the filetype they apply to. In this example we have a swift.vim file. In ftdetect files we decide whether or not we want to set (or override) the filetype of a file in different situations. For swift.vim this file looks like this:

" ftdetect/swift.vim
autocmd BufNewFile,BufRead *.swift setfiletype swift

Here we’re using setfiletype on any files named *.swift whenever we create a new file or finish reading an existing file. setfiletype is a friendlier way to do set filetype=swift. If the filetype has already been set setfiletype will not override it. Depending on what our syntax plugin does that might not always be what we want.

ftplugin

Next we have the ftplugin folder (:help ftplugin). This lets us execute arbitrary Vimscript or set other settings whenever the file is sourced. Files in Vim’s runtimepath (:help rtp) nested in ftplugin folders are sourced automatically when the filename (before .vim) matches the current filetype setting (we can read this setting with :set ft). So after our ftdetect file sets the file type as swift, Vim will source the swift.vim file nested in the ftplugin folder. In swift.vim that file looks like this:

" ftplugin/swift.vim
setlocal commentstring=//\ %s
" @-@ adds the literal @ to iskeyword for @IBAction and similar
setlocal iskeyword+=?,!,@-@,#
setlocal tabstop=2
setlocal softtabstop=2
setlocal shiftwidth=2
setlocal completefunc=syntaxcomplete#Complete

All of these settings are things that apply to how we want Vim to act when editing Swift files. The most interesting here is when we set iskeyword. Here we’re adding a few symbols so that when we execute commands such as diw those symbols will be treated as just another character in the word instead of treating them as delimiters breaking words.

syntax

Now we get to the meat of syntax plugins. Files nested under the syntax folder named after the current filetype setting are sourced in order to actually highlight the file. Syntax files contain rules in order to match patterns in our file. Here are a few examples:

" syntax/swift.vim
" Match TODO comments
syntax keyword swiftTodos TODO XXX FIXME NOTE

" Match language specific keywords
syntax keyword swiftKeywords
      \ if
      \ let
      \ nil
      \ var

Both of these examples define new syntax matches for keywords. Keyword matches should be used for the language’s reserved words that should always be highlighted as such. Matches can also get more complicated:

" syntax/swift.vim
" Match all Swift number types
syntax match swiftNumber "\v<\d+>"
syntax match swiftNumber "\v<\d+\.\d+>"
syntax match swiftNumber "\v<\d*\.?\d+([Ee]-?)?\d+>"
syntax match swiftNumber "\v<0x\x+([Pp]-?)?\x+>"
syntax match swiftNumber "\v<0b[01]+>"
syntax match swiftNumber "\v<0o\o+>"

Here we’ve defined syntax matches with the match argument allowing us to match regular expressions (see :help magic for what’s going on here). These specific regular expressions match all of Swift’s number types. Some examples of matched numbers with these:

5
5.5
5e-2
5.5E2
0b1011
0o567
0xA2EF

Syntax matching can get even more complicated when we start matching function declarations and other statements. For example:

" syntax/swift.vim
" Match strings
syntax region swiftString start=/"/ skip=/\\"/ end=/"/ oneline contains=swiftInterpolatedWrapper
syntax region swiftInterpolatedWrapper start="\v\\\(\s*" end="\v\s*\)" contained containedin=swiftString contains=swiftInterpolatedString
syntax match swiftInterpolatedString "\v\w+(\(\))?" contained containedin=swiftInterpolatedWrapper

Here we’re matching Swift strings that are wrapped in double quotes. In the first line we start out by matching the swiftString region which defines start, end, and optional skip patterns. Here the skip pattern allows us to have escaped double quotes in our strings. We also pass some other arguments here. oneline specifies that this pattern can only span a single line. contains specifies what other syntax groups we’ve defined can exist within our region. In this case a string can contain interpolated arguments similar to Ruby. In Swift interpolated strings look like this:

"2 + 2 = \(2 + 2)"

The second line shows how we define the region enclosed within the interpolated string. Our start region specifies the starting \( pattern along with any number of optional spaces while our end region matches spaces and the closing ). We specify that this is contained within our strings so it is not matched elsewhere and that it contains our third syntax group. In our final group we specify what can be contained within the interpolated portion of our string.

When writing syntax files for entire languages, we’ll have to create matches using each of these types of groups to match different things. The hardest part of this is dealing with collisions. We have to be very aware that what we’re changing won’t break another portion of our highlighting.

Once we have our matches we need to tell Vim how to highlight them in a way it understands. Here are the highlighting associations for swift.vim:

" syntax/swift.vim
" Set highlights
highlight default link swiftTodos Todo
highlight default link swiftShebang Comment
highlight default link swiftComment Comment
highlight default link swiftMarker Comment

highlight default link swiftString String
highlight default link swiftInterpolatedWrapper Delimiter
highlight default link swiftNumber Number
highlight default link swiftBoolean Boolean

highlight default link swiftOperator Operator
highlight default link swiftKeywords Keyword
highlight default link swiftAttributes PreProc
highlight default link swiftStructure Structure
highlight default link swiftType Type
highlight default link swiftImports Include
highlight default link swiftPreprocessor PreProc

Here we are linking one of our match group names to a Vim-specific keyword based on what our group matches. We can see all available matches under :help group-name where they are highlighted based off our current color scheme. While it may be tempting to link a group to a type based on its appearance in our color scheme, it’s more important to maintain the match’s semantic meaning so they will work as expected in other user’s color schemes.

indent

Finally we have the indent folder. Again, it contains a file named after the filetype for how indentation should work as we’re writing in Vim. Personally I think handling indentation is the hardest part of writing syntax plugins. The goal in these files is to do one specific thing. Set our indentexpr (:help inde) to a function that calculates and returns the level of indent for the current line. While that may sound simple, taking the context of that line into account can be extremely difficult. Also, just like with syntax files, we have to worry about collisions. Let’s look at some of this file for swift.vim.

" indent/swift.vim
setlocal indentexpr=SwiftIndent()

function! SwiftIndent()
  let line = getline(v:lnum)
  let previousNum = prevnonblank(v:lnum - 1)
  let previous = getline(previousNum)

  if previous =~ "{" && previous !~ "}" && line !~ "}" && line !~ ":$"
    return indent(previousNum) + &tabstop
  endif

  ...
endfunction

Here we’re setting the indentexpr to our function. Then inside our function we’re getting some context around the line we’re trying to indent. The first thing we notice is the v:lnum variable (:help lnum-variable). This is a predefined variable (:help vim-variable) that is set automatically inside indent functions. It gives us the line number for the current line to be indented. We can then use it along with some other Vimscript to get the text on that line along with the text on the last non-blank line above it. Using this information, along with some pattern matching, we can build out cases where our lines should be indented more, less, or the same as the surrounding lines.

Wrapping up

Combining these four Vim plugin file types you can contribute to syntax plugins you have found bugs in, create syntax plugins for additions to languages or entire languages. Doing so you can help Vim continue to stay awesome as new programming languages come and go.

What’s next?

06 Oct 00:44

Design Sprint Case Study: Merck Development Portal

by Kyle Fiedler

We recently completed a four-day product design sprint with Merck. They are actively building their development team and looking for a central place to share Merck specific development knowledge and tools. There is a potential for aspects like APIs, code snippets, and general procedural knowledge to be shared, thereby saving the company developer time and money. Their hope is to encourage developers to more readily share their knowledge and code across teams and contents.

Day One – Understand, Diverge

Since the team had only a general idea of what to build, we ran a number of activities to better understand what problems this project should solve. We played Who, What, Where, When, 5 Whys and completed a card sorting exercise. We ran these activities to refine the goal for the project and what would make it successful.

Card Sorting

These games nurtured a healthy debate on whether the application’s primary job to be done was to share code and knowledge among developers or if the priority was to show how much money is being saved with code reuse for managers. The assumption was that if managers have buy in, they would force developers to use the application. If we got developers interested, the application would encourage education and reuse of code. We would be able to calculate financial savings later.

We decided that the primary job was to spread knowledge and code, and that quantifying time and money savings would eventually grow from this primary goal. We recorded the conflict so we could return to it later, if necessary.

After starting mind maps, crazy eights and storyboards, the debate resurfaced regarding the primary problem we were trying to solve. Because it was later in the day, I recorded a new challenge statement to address the contrarian thought and suggested that everyone break early to contemplate the issue overnight, individually. My intention for taking a step back from the project was that it would allow the team to return refreshed the following day.

Storyboards

Day Two – Diverge, Converge

The following morning, we dove back in. We briefly discussed our two problem statements, and how this major conflict and assumptions would be a highlight of our user interviews and problem / solution tests. Together we converged on a third and final challenge statement, which was both shorter and simpler than the first two.

Make it easy to share development work and knowledge at Merck to spread knowledge, save developer time and resources and quantify that savings.

We reflected on the critical path that we were following with the first statement and analyzed the similarities and potential differences that this new challenge statement introduced. We examined the storyboards that we completed the prior day and found that much of our previous work would carry over nicely to our new statement.

Storyboards

Despite our progress, there was one thing that I felt was holding us back. It wasn’t clear to me what Merck wanted developers to share, and what form this would take and whether developers would want to share it. We completed another card sorting exercise to organize the team’s thoughts about the types of posts and content they sought. We organized them based on what we felt was most important.

Now with a clear goal and a better understanding, we completed several more rounds of mind maps, crazy 8s and storyboards. With each round we slowly reached a consensus on what the user flow would be for each of the steps in our critical path. At the end of each round, we reflected back to our challenge statement to make sure that we were still on track.

Because we had completed so many group exercises, developing the layout of each page went relatively smoothly and quickly. We wireframed each screen on a whiteboard based on the sketching we had completed in previous storyboards. We then listed the assumptions we had been making throughout the two days and drew conclusions regarding which aspects we should try to validate with some user research before the user interviews and problem / solution tests.

Storyboards

Day 3 – Prototype

I spent the entire day creating a prototype using Sketch and Invision. I was easily able to recreate our whiteboard wireframes in Sketch and place the exported files into a folder to be synced. The primary issue that I had with Invision was the lack of support for any kind of form input. It was also time-consuming to design states for buttons and form inputs for each wireframe.

Prototype

Day 4 – Test

User interview and testing proved very useful. We both validated and invalidated a majority of our assumptions about developers at Merck and what our application would accomplish. We learned that developers were already sharing a lot of code and knowledge within Merck through their personal network. The longer that the developer had been with Merck, the more they had shared, and the more knowledgeable they were about who they considered experts in particular fields.

Outside of the company, however, most developers were not participating in online discussions, blogs or forums. This was one of our key indicators on whether they might be willing to contribute within the company. The user interviews and problem / solution tests did identify some problems and invalidated some assumptions that we had. Users weren’t clear on the types of posts that they could make, and the barrier for entry was a lot higher than we previously thought.

Design Sprint Wrap-up

In the end, we didn’t feel strongly enough that the solution we created in the prototype would be worth the time to build as it was. By testing out the quick prototype we saved Merck several weeks of development in the wrong direction and in the end potentially saved the product. After some discussion, we agreed to do another shortened sprint to tackle the problems we found with the last prototype. This way we could continue to refine some of the ideas that came out of our diverge sessions on day one and two with the new found information from testing.

01 Oct 15:24

Microsoft Skips ‘Too Good’ Windows 9, Jumps to Windows 10

by John Gruber

April Fool’s joke in 2013, actual news story in 2014.

10 Sep 17:33

Writing Skills

I'd like to find a corpus of writing from children in a non-self-selected sample (e.g. handwritten letters to the president from everyone in the same teacher's 7th grade class every year)--and score the kids today versus the kids 20 years ago on various objective measures of writing quality. I've heard the idea that exposure to all this amateur peer practice is hurting us, but I'd bet on the generation that conducts the bulk of their social lives via the written word over the generation that occasionally wrote book reports and letters to grandma once a year, any day.
04 Mar 19:05

Worth Waiting

by John Gruber

Speaking of Steve Jobs’s birthday, Tim Cook tweets:

Remembering Steve on his birthday: “Details matter, it’s worth waiting to get it right.”

That’s Apple in a nut.

27 Nov 15:45

autossh

autossh:

autossh is a program to start a copy of ssh and monitor it, restarting it as necessary should it die or stop passing traffic.

22 Nov 15:35

The Lean Enterprise

by Obie Fernandez

Theleanenterprisebook

I'm happy to announce that my esteemed business partner and I are writing a mass-market book about how enterprises can adopt Lean Startup techniques to think like and compete with Silicon Valley. We're drawing from our experience and the wisdom of our wide network of contacts at Lean Startup Machine to make the book hard-hitting and relevant to modern managers.

If you have an interesting Lean Startup case study or are trying to implement Lean Startup in your company, I'd love to hear about it. Click here to get free early access to book content, all we ask for in return is your feedback.

06 Sep 18:39

My Design Apprentice Experience

As the middle of September approaches, I am about to finish the last week of my three-month Design Apprenticeship at thoughtbot in their San Francisco office. It has been a summer of ample personal and professional growth.

Before I joined the apprenticeship in June, I had just finished my last semester in college. Because my American Studies major was perfectly unrelated to design or engineering, I had prepared myself for this apprenticeship by bootstrapping my own design education during my free time in school: I made Wordpress websites for my friends’ clubs, created logos for student and campus organizations, and led a student-run design consultancy. Despite these experiences, I knew that there was only so much that I could learn on my own before I needed to gain true professional experience to further my career. The next sensible step was to participate in apprentice.io.

The apprenticeship focuses on training people in the skills required to become a full-time developer or designer on the team. thoughtbot developers and designers not only possess technical expertise to create products, but they must understand how to meet client needs as well. After all, there are no project managers, so the developers and designers are the consultants.

Given the structure of the company, I was placed in a professional learning environment where I was expected to acquire the technical prowess needed to implement my designs, interact with clients, understand their needs, and work collaboratively with other developers and designers while directing my own work.

I’ve learned a lot through my mentors, the open-source projects that I’ve contributed to, and self-guided learning. Today, I collaborate with a team of developers and designers using a formulated Git flow, write HAML and SCSS using best practices, prefer Vim as my go-to text editor, and much more. Aside from developing my technical abilities, I’ve also gained product skills from real-life and hands-on exposure to client work. I co-led five-day ideation-based product design sprints, conducted user interviews and user testing, and learned how products and businesses grow.

It has been an incredibly rewarding three-month intensive learning period. Given the intensive nature of it, I would primarily recommend the design apprenticeship only to those who are 100% certain that they want to become a product designer in the technology field. We encourage that our design apprentice applicants to have designed and coded HTML/CSS websites before, have a portfolio showcasing a solid grasp of visual design principles, and understand why it is that they are interested in designing products and experiences for people.

If you do not feel ready to apply for the apprenticeship, thoughtbot’s Learn program is a great resource for those getting started. Also, some of the designers here are available via email if you have questions about design, need learning resources, or want to know how to get started on jumpstarting your design career.

  • Lisa (me): lisa@thoughtbot.com
  • Alex: alex@thoughtbot.com
  • General apprentice.io email: apply@apprentice.io

However, if you feel ready to take the next step to launch your design career in tech, then apply for the apprenticeship!

29 May 11:38

Google Hangout for Standups and Interviews

We’ve been experimenting with Google Hangout for meetings such as daily standups with remote team members and interviews with remote candidates.

We concluded this experiment was a success.

It’s nice to have a recurring calendar invite to open, click “Join Hangout” and start talking.

Calendar invite

Google Hangout is sometimes choppy over wifi. The settings need to change when we switch from laptop to monitor, so we often are without sound for a few seconds before changing the “FaceTime Camera (Built-In)” setting to “FaceTime HD Camera (Display)”.

face

We’ve noticed in longer meetings, we sometimes need to refresh the page if sound starts to get choppy, presumably to clear some buffering.

We’ve noticed during Hangouts that the sound captured by a Macbook Air’s internal microphones is often muffled. We generally have Macbook Pros for better performance of test suites, but there are a few of us who have Airs. We have started to fall back to phone calls for sound in those cases.

Overall, it’s always better to see someone’s face.

Written by Dan Croak.

13 May 01:50

★ Web Apps vs. Native Apps Is Still a Thing

by John Gruber

Michael Copeland, two weeks ago writing for Wired:

Marc Andreessen has a thought exercise for you.

Let’s say we all grew up in tech world where we only used tablets and smartphones. Then one day, someone comes up to you with a 27-inch display hooked up to a notebook. You could have everything you have on your tablets and smartphones, and then some. Except you don’t have to download anything or update it. Everything is the latest and greatest, and just one click away. If you are a software developer, there are no gatekeepers telling you if your latest creation is approved, or when you can add the latest flourish.

“We would be like, wow, that’s great,” Andreessen says from his office at venture capital firm Andreessen Horowitz. “It’s why in the long run the mobile web is going to dominate native apps, and for the same reason that on the desktop the web dominates apps. When the web works for something, it works way better in a whole lot of ways than a downloadable app.”

There’s some conflation here between two different debates. The first is desktop vs. mobile computing — Mac OS X and Windows vs. iOS and Android. Trucks vs. cars, to reuse Steve Jobs’s analogy.

The other is native apps vs. web apps, where by web apps I mean apps that run in a web browser tab. These are separate debates for the obvious reason that you can choose between either type of app (native or web) on either type of computer (desktop or mobile).

The growth in desktop computers is over, and it’s never coming back. Some people, but only a few, who grow up driving cars are ever going to decide they actually need a truck. Tablets and smartphones are already consuming all of the growth in personal computing, and it’s only going to accelerate as the hardware and software begin to mature. iPads and iPhones are adolescent, at best.

Andreessen does have a solid point in the fact that app stores are in some ways a pain in the ass — particularly Apple’s App Store, with its deliberative and at times opaque approval process. But app stores are mostly only a pain in the ass for developers, not users. Installing and especially updating apps through app stores is obvious and easy for all of the modern mobile platforms. And even for developers, there are aspects that are superior. With paid apps, for example, the apps store model is a win. The user taps a “Buy” button and enters their password, and boom, they’ve bought the app. Web apps can’t do that. (Paid apps are not of much interest to venture capitalists such as Andreessen.)

There is a trust factor at play: having no gatekeeper is a good thing for developers in terms of convenience, but not necessarily for users in terms of security, privacy, and system stability. The same gatekeeper annoying developers with an approval process is the trusted source telling users, This app is OK, no harm will come to you from installing it.

iOS has proven that user experience matters, not merely among a picky few but in the mass market. The quality of the user experience isn’t always primary, but it can be, and when it is, native still wins every time.

Today, in 2013, even the best-crafted mobile web apps come nowhere near the quality of experience of the best native apps. In fact, with but a few exceptions, the best mobile web apps today still don’t approach the quality of the first batch of native iPhone apps from 2007.1

Facebook, bless them, has it right. What’s great about the web is ubiquitous network availability, not running within a browser tab. Websites are just services, and what you see in a browser tab is merely one possible interface to that service. The best possible interface to that service is often, if not usually, going to be a native app, not a web app.

Andreessen has been singing this same song since the ’90s, when he was leading Netscape. But web apps today are no closer to obviating native apps on mobile devices than they are on the desktop, where we’ve been using and developing them since Bill Clinton was president of the United States.

There are no absolutes in either of these arguments. No one is arguing that desktop computers are obsolete or will be any time soon. Nor is anyone arguing that all apps should be native.

Web apps absolutely have their place. I use several, daily. I’ve even made a few. But most of the ones I use, I do so because they have no native app counterpart, and I wish they did, so that I could use the native app instead.2

The dynamic remains unchanged. Web apps are the best way to reach the most possible people with the least effort; native apps are the best way to create the best possible experience.


  1. One such exception: the excellent weather app Forecast.  

  2. Not a day goes by that I don’t crave a native Mac client for Glassboard

10 May 15:12

Rebecca and I will be Keynoting at QCon London

QCon invited Rebecca and I to do a keynote at QCon London (March 7). Over the last year or so we’ve been seeing more and more of a change in how organizations think about data, so that seems a natural choice to talk about. Our clients are seeing larger volumes of data, that they need to analyze more quickly and more cleverly. We’re seeing different technologies for data storage that have loosened the vice-like grip of relational databases. And we find our profession needs to start thinking about what our responsibilities are in managing all of this information.