Hey, we are pleased to let everybody know that Sprint.ly took “Best in Show” in the Under the Radar Conference in San Francisco today.
We saw a lot of neat companies on stage today, and find it very humbling to be picked as best. It’s really fun to lay out our vision of the future of the Mobile, Global Workforce and describe how Sprint.ly is leading the way.
Thanks to all of our customers whose patronage and great feedback allow us to keep innovating.
We’re excited to announce the release of Sprint.ly 1.5. This release has been in the works for months and was entirely focused on speed, quality, and polish. From the core backend query interface to the way we handle Backbone collections on the frontend, Sprint.ly is now leaner, meaner, and more fun.
Despite all the refactoring that’s been going on, the team did manage to sneak in a slew of new features and polish that you all have been asking for. Let’s take a look at a few of the new features in Sprint.ly.
Probably the most noticeable update is that you can now attach files to an item when you create it. Simply drag files into the item description and drop.
We’ve also added two new filters: “Loved by” and “Mentioning”. The “Loved by” filter lets you filter for items that have been marked as a favorite by a specific person on your team. The “Mentioning” filter will show items in which a specific person has been mentioned in a comment.
Quick Sort Bar
The Quick Sort Bar, or QSB as we refer to it, has gotten a number of much needed improvements. Here’s a quick rundown of what you can now do with the QSB:
You can now drag items from Backlog and Someday columns directly into the QSB.
You can now click and drag the individual boxes within the QSB to resort an item without having to drag its card from the Backlog column.
The QSB is now on the permalink page for items in the Backlog. This means you can now prioritize an item within the Backlog from its permalink page.
The real action in Sprint.ly 1.5 is largely behind the scenes. We completely rewrote the backend to query the DB more efficiently and do better/smarter caching.
In addition to this, we’ve almost entirely rewritten how the frontend talks to the backend. We now have a single shared collection that is cached in local storage. In addition to this, each item is stored in local storage, which makes loading permalink pages super snappy.
We’ve gone over the UI with a fine toothed comb and made as much of the UI optimistic as possible. Bulk edit, making comments, sorting, dragging, deleting, scoring, etc. are all rendered the second you click.
When I first saw the optimistic UI on the bulk edit I was like:
Item Mentions & Card Popups
We’ve also freshened up our Markdown processor so that it does two things:
When you mention an item it now shows up in the activity feed for the item that was mentioned.
We now show the item card on hover for any item numbers that are mentioned in a comment or description. No need to surf to the new item just to take a quick glance or reassign it (all item cards are in-line editable)!
We hope you enjoy the new Sprint.ly 1.5! Pardon me now as we’ve got more stuff cooking in the kitchen that I need to attend to.
Today I’m pleased to announce that Sprint.ly has hired Matthew Work as Chief Strategy Officer.
Matt has been working with the team as an advisor since this last fall. When the time came to hire someone to work full-time on our burgeoning business operations, the choice was clear. Moving forward he will be taking point on marketing, sales, and business operations (That sound you hear is me breathing a sigh of relief).
Matt has devoted much of his career to helping businesses and developers collaborate together more effectively. Before joining Sprint.ly, Matt was General Manager of Pivotal Tracker at Pivotal Labs prior to the EMC acquisition. Prior to that he founded Cohuman, which was acquired by Mindjet. Matt’s passion for agile methodologies and workplace collaboration are apparent to anyone who’s worked with him.
Beyond his work with developers Matt has built and sold a few companies, taken one public, and spent time as VP of Research at Alexa. You can read more about our newest sprinter on LinkedIn.
A few years back, I worked at a company which made a very simple mistake in how they delivered product, which unduly limited the amount internal innovation: the omission of why.
The company was in the advertising space which is a morass of opaque terms like “piggyback pixels”, “real-time boom lists” and “demand-side platforms”. Contrast that with something like a music player. Most people understand how music players should work, why you might want one and, if pressed, come up with some potentially innovative new features. Advertising, on the other hand, isn’t as clear. What features does an advertiser look for in their ad buying platform?
The way we dealt with this complexity was by pushing the burden of knowledge onto a few experts within the company. These folks distilled customer desires into features and wrote up a implementation plans. When they vetted this with the others on the business-side, they gave what amounted to a very specific todo list to engineering.
This is harmful because, as a business, you’re trying to hire the best and brightest folks across your organization. By not allowing your employees to operate on the same data across the organization, you breed a culture of assembly-line workers: folks who don’t ask questions, just do what they’re told. This is not what you want the best and brightest to be doing!
The key behind solving this issue is sharing the whys behind decision. By coloring in some of the context around why a feature is necessary, you allow lateral thinking among your employees. If I, as an engineer, can accomplish the same “why” for a given story but with dramatically less work than the proposed implementation plan, that’s better for everyone involved.
At Sprint.ly, we address this by including the “why” as a central part of any user story. By answering why, you educate everyone else in the business of customer needs and reinforce the notion of consistently delivering value.
Empowering people in your organization is important for increasing throughput and minimizing the need for active management. Sharing knowledge and the expression of intent (e.g the whys of something) is paramount. Without it, you’re hamstringing the development of your employees and the success of your business overall.
At Sprint.ly, our mission is to help you seamlessly interact with your coworkers. A key aspect of this is that we allow people to work in the way that best suits them. If you’re a developer, we have command line tools and deep GitHub integration. If you’re on the business side, we have rich email interaction. Until today, there’s been a class of potential users who’ve been left out of this equation: the Luddites. Not everyone has made the jump to all things digital, and for those, we’re releasing Sprint.ly Paper.
Sprint.ly Paper is a downloadable resource which will allow these users to write in their user stories using technology they’re already familiar with: paper and pencil! Just as we’ve integrated with the best of breed developer tools like BitBucket and GitHub, thanks to their open API, we’re happy to say that Sprint.ly Paper interfaces with the US Postal Service in the way you’ve come to expect. Just fold up your Sprint.ly Paper, put it in an envelope, and mail it to the project manager on your team. No more time-wasting face-to-face meetings. You’ll be back to doing business just as it was done in the 1950’s!
As with everything we do, we hope this brings your team closer to one another, helping you get your work done even faster! To get started, just right click on the image above, open it in a new tab, and print to your heart’s delight.
At Sprint.ly we’re big fans of shipping. So much so that we militantly remove anything that stands in our way of shipping, including process.
“You can’t ship process.” – Ethan Kaplan, VP of Product at Live Nation
Our approach, which we call Non-Blocking Development, isn’t so much a methodology as it is a pragmatic approach that optimizes for shipping working software over everything else.
As far as the Agile Manifesto goes, we’re in total agreement that the priority of software development is to ship working software, but we disagree on two key aspects:
Invest heavily in automation vs. “Individuals and interactions over processes and tools”
Treat your makers as asynchronous threads. vs. “The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.”
The agile manifesto was written years before the modern automation and DevOps movement really got under way. The cloud didn’t exist. Servers and services we rely on weren’t ephemeral in nature. If you’re not heavily investing in automation and tools, you’re exposing yourself to risk in the cloud and hindering your technical team’s ability to ship software.
Another very anti-agile pattern in NBD is that the business should move entirely to asynchronous communication. While we agree that face-to-face communication is the most efficient and effective method of communicating, we do not believe it’s pragmatic in today’s working world. Globalization is happening at a frenetic pace. Businesses have teams dispersed across the globe. Strictly adhering to this principle would, in fact, have the opposite effect on businesses.
The realities of managing knowledge-based workers dispersed around the globe are leading many of us to re-think our approach. Strictly adhering to process dogma won’t fix inherently human problems like timezones.
“You have to be agile in your approach to agile.” – John Quinn, VP of Engineering at Gilt Group
We use our own product Sprintly a ton and love it, but over time we noticed our interface slowing down as it tried to render large lists that would contain hundreds or even thousands of items. As Donald Knuth once said, “Premature optimization is the root of all evil.” so we knew we needed to focus on building a great product over performance early on, but now that our product has grown and customer base is maturing, it’s time to take on making Sprintly fast.
Over the last few weeks we built blazingly fast and performant item columns…even when rendering thousands of items! Check it out:
The update was tweeted about from the main Sprintly account. Immediately we were asked to explain how we accomplished this, so I’ll go through and discuss the main approaches to building performant interfaces and explain why we decided to tackle it the way we did.
Finding the Cause of Slow UI Performance
It’s amazing what kinds of things Chrome dev tools can expose, but in our case it was blatantly obvious we needed to tackle how the item columns render. In the video you’ll see the old lists could take almost a minute to load thousands of items. In the new version, instead of rendering all the items at once, we developed a way to lazy load items as they came into view.
Slow Rendering of Backbone.JS Views
We use Backbone.JS for our application. The most common issue I see when using Backbone is that it’s encouraged to have views render themselves. That’s usually fine, but when you start to have large collections of view to render and you loop through them to render views individually, you are actually forcing the browser to repaint and render with each item injected into the page. Like I said, it’s not a problem if you are only rendering a few view, but it adds up quickly to become a performance bottleneck.
This would insert the view into the DOM 1000 times. Bad thing to do. And in our case this ItemView has many other subviews, so the issue was compounded by each subview added.
There’s a few main approaches you can take to tackle fixing rendering issues.
Pre-render the HTML (server-side)
Batch render the views
Lazy-load the views
I’ll walk through each of these approaches at a high level and give reasons why we settled on #3 for large lists of items.
Approach #1: Pre-rendering HTML
One of the biggest benefits to pre-rending all of your HTML is with public websites that need to be indexed by search engines (note: you can make your AJAX application crawlable, but it isn’t automatic).
The other main advantage is that the client doesn’t have the initial overhead of processing merging of JSON and HTML templates.
Render your entire page on the server and then bind views to the existing HTML fragments later. This is the basic principle behind Twitter’s new Flight framework. Just find the elements and then bind the views to them after the page loads to attach behavior.
The major caveat to this approach is you have to duplicate your rendering logic to the server. We didn’t chose this method both because the contents of our application doesn’t need to be indexed by search engines and all of our rendering currently happens in mustache templates, so it would take a fairly large revamp of our current codebase to migrate to something like Node.JS to render the templates on the server. It might be a good approach longterm, but we wanted a quicker win.
Approach #2: Batch Render Views
Instead of rendering each individual module on the page, you can decide to load all the HTML up into some type of string, array or detached DOM node and then insert then insert your views into the page all at once. This leads to touching the DOM less and, in turn, the less times the browser has to repaint itself.
Render all of your HTML into a string, array, or detached DOM node that will be inserted into the page at a later time.
Well, technically, I did this where I could. Batch rendering is always a good idea and you should do it whenever possible. But in this case we weren’t able to batch render for list items because we’re using D3.js to bind data to DOM nodes and sort the nodes in the DOM. It works like magic, but initially D3 wants you to render out at least one node per data element. To get around this we render placeholders (I’ll get into that next).
Approach #3: Lazy-Loading Views
You don’t have to render all the items on initial page load. Instead, load them as you need them.
Render enough to paint the current view, then as things come into view (usually on scroll), render items enough to fill the window.
I explained the main benefit is that you don’t have to render all the views all out at once. You can load a subset and then load the rest later.
The trick with getting this to work is you always have to determine what is in the view and render the appropriate views.
Checking What’s in the View on Scroll
Looking into the current view for what to render can get expensive, so we don’t want to do this on every scroll event. So we use a concept called debouncing. Check out the debounce method in underscore.js. What happens is instead of firing an event every time you scroll, you just fire it at a maximum of a certain amount of milliseconds.
So with debouncing we can run a method to check the view max of every 150 milliseconds and not slow down the interface with excess function calls.
Smart Rendering with requestAnimationFrame
Enter requestAnimationFrame. With the requestAnimationFrame polyfill, we can wait to render until the browser is ready to paint the next animation frame in a cross browser way. Using rAF prevents DOM manipulation updates from *stacking* and slowing down the UI. Game developers might be familiar with a runloop where changes are flushed…that’s what’s happening here. Frameworks like Ember.js are starting to incorporating this runloop concept where DOM changes are written to a buffer and then *flushed* on each frame.
So that’s how we lazy load list items efficiently. We use function debouncing with requestAnimationFrame to prevent the view check from happening too frequent, and to wait for the next frame available to render.
Finding Un-rendered Elements in View
So far I haven’t dived into what’s in getItemsInView() function, but it’s actually simpler than you might think at first. Since we are rendering un-rendered items in a list, we just have to find the top element in the view and the bottom element in the view and render those. We can do that with document.elementFromPoint function. elementFromPoint takes an “x” and a “y” param and tells you what element is showing at that point.
When I first started programming in the late 1990s my toolset was comparable to that of a manufacturer a hundred years ago; we were forced in those early days of the web to build everything ourselves. Need web framework? PHPNuke was the best thing going. Need a server? Build them yourself or buy some. Need server automation? Build it yourself. Want to write tests? You’ll probably need to write your own unit test framework. Want to do a code review? Bust out the projector and find a room.
However, the Internet dramatically changed how software developers shipped software. No longer bound by boxed software delivery schedules, developers began iteratively shipping software as it became ready. In 2001, this change in approach was codified under the banner agile/scrum with the signing of the Agile Manifesto.
Fast forward to 2013 and another shift in technology is causing a fundamental shift in the software development process. The programmatic nature of the the cloud world we live in, along with a more sophisticated toolset, have enabled us to ship software in real-time.
As a result, many of my colleagues and more than a few of Sprint.ly’s customers have dramatically changed how they ship software. The best outline I’ve seen on this newer, more-agile-than-agile approach to shipping software is Scott Chacon’s post on GitHub’s flow. This is the software development workflow that we use to ship Sprint.ly and the workflow that Sprint.ly most closely mimics.
I’m calling it Non-Blocking Development and it’s entirely based on the notion that shipping quality software quickly is a competitive advantage.
The core tenants of Non-Blocking Development (NBD) are:
Invest heavily in automation. This means spending considerable time on implementing test-driven development (TDD), continuous integration (CI), DevOps, etc.
All development is done via branches. This minimizes exposure to risk by keeping your master branch clean and isolating changes.
Branches are tested and deployed automatically on approval. This keeps unfinished features from arbitrarily gating the deployment of completed features.
Treat your makers as asynchronous threads. If Sally is finished with her story in 2 days, while Bob takes 5 to finish his, why should we arbitrarily wait 3 days for Sally’s story to ship?
Notice what’s not there? There are no sprints. No velocity or abstract points to track. No more iteration schedules. No dates.
What does this mean? It means that our workflow tools need to change. We need to focus less on attempting to control the messy complexities of human-driven workflows and more on cataloging and capturing what’s going on as it happens.
It also means we’ll need to take the notion of cross-functional teams to the extreme. Salespeople, business development, marketing, and PR will need to be more closely embedded into the software development process. It means us software developers will need to learn a lot more about how the business functions and how software can enable the business to operate more effectively.
As software continues to eat the world, I believe businesses will be forced to invest heavily in NBD. Why? Because businesses can’t afford to ship twice a month when their competitors are shipping twice an hour.
This post is based on a talk I gave titled “Couples Counseling for Software Development” at GROW Talks in Vancouver. The slides are embedded below.