Have you and your partner had this conversation before? “Where do you want to go for dinner? I don’t know, where do you want to go?” Cobble (launched after first venture, idk tonight) is a startup based in NYC whose mission is to help couples answer this question.
Cobble partnered with YML to build the company’s first mobile application (iOS) focused on enabling couple decision-making through its curated content platform.
Forbes also showcased Cobble, focusing on the originality of the concept and product. As Cobble's founder, Jordan Scott, shared in the story, "All of the apps that come out today are all about taking your time and attention and energy. The goal for us—not only because we want to be a successful business, but because we think it’s good for the world—is to give people their time back. Get to a decision as quickly as possible, and then you’re out into the world."
YML ultimately built a custom, mobile application platform with a CMS and data feed component, which has the ability to scale as the company grows. It was a phenomenal concept that the YML team was proud to bring to life.
In The News
"How A 25-Year-Old Created A Tinder-Style App That Will Transform Your Next Trip" Forbes
"Startups To Watch: Cobble, Oula And More" Crunchbase
Miscommunication is far too often responsible for defects in digital products. A clear design system goes a long way to reducing the risk of these types of defects.
By Sami Eljabali, Engineer, YML
The common thread of the most impactful digital products today is the design system; a common language for designers and developers to speak that guides the creation of a product, and facilitates the best possible experience for customers. That all starts, though, with design review meetings, which tend to be the most dreaded meetings amongst developers and designers, as well as their most frequented place of contact.
"This needs more padding." "That isn't the same blue as on the mockup." A meeting where one wonders why the other can't clearly see what they've being coding for the past few weeks, and the other wonders if they’ll ever be freed of the other's pixel chasing dreams.
It's a mind numbing meeting for all parties involved. The reason is obvious: it's a game of spot the difference tasked by grown adults. A game even elementary students find boring eventually, yet routinely done by professionals seriously.
Has our industry grown complacent to this game? Is it even seen as a problem worth eliminating in the first place?
Being in an industry that's notorious for automating others' processes, it's about time we looked internally and automated one of our own. In this article I'm going to help you do just that for your design and engineering teams by introducing the power of a design system, brought to life by the concept of design tokens, better practices, and how to best communicate them across the board.
I’m then handing you two free projects for both Android and iOS that will help jump start your process in having your developers and designers thank you for the extra time they now have to play Pictionary post sprint reviews.
In trying to explain what a design token is, it’d help define what its parent system, a design system, is first. I liked this definition by Grinaker:
“A design system maintains the visual and functional elements of an organization in one place, in order to fulfill its brand principles through design, realization, and development of products and services.”
When it comes to mobile development, a design system encompasses all building blocks used, how they behave, when to use them, as well as all quantitive values used to describe pages visually. These visual, quantitive values can be categorized as design tokens. Think of these values as those used by designers in mockups that are then absorbed and used by developers in application development. These values include, but are not limited to: paddings, margins, text sizes, and color values.
The value in defining design tokens
Universal team language
Imagine a designer mocks up a mobile page with a margin of 4px (pixels) between two buttons. An Android developer then in implementing the mockup, has the margin as 4dps (density-independent pixels), as it's Android's standard unit of measurement for spacing.
In reviewing the page on a testing device, the designer measures the margin size in actuality being 6px. The designer points out the mismatch to the developer, who then show it's accurately 4px on a differing testing device.
DPs scale in pixels according to the phone at hand’s screen size & resolution. iOS similarly use Points that too scale similarly between different iPhones & iPads.
Miscommunication is far too often responsible for defects. A clear design language goes a long way to reducing the risk of these types of defects.
Edward Cessna, Senior Director of Engineering, YML
The need here is clear: to instill a unified language to describe design tokens, in this case spacings, amongst all parties involved in development to avoid painstaking miscommunications from reoccurring time and time again.
The cement between building blocks
If widgets are an app’s building blocks, then design tokens is its cement that glues them together. Their usage is commonly used in application development and the implications are many should they not be well thought of nor defined.
If colors for example in an application are not defined, then developers will hardcode them impromptu as they see fit resulting in poor UX, as pages have no rhyme nor reason in color scheming. Should spacings be defined, but not as well thought of for example, an app may not be as visually pleasant from users’ standpoint.
Better practices in defining design tokens
Values ought to stand out from one another:
A common pitfall of curating design tokens is creating far too many of them that are too close in value to one another, which then makes it hard to discern when to use one over another.
When thinking of how to cut up real estate of a mobile page, convention states to create a grid (rows & columns) where each are of size 8. Naturally when defining spacing values, first thought is to go by 8 increments, where the first few values are fractions of an 8th. Let’s see visually what the problem with that is.
Bad linear growth using f(x)=8x. Notice how hard it is to tell side by side values at 16dp onwards.
Good exponential growth using f(x)=2^x. Notice how these values shine more.
“Name Each Step for Memorable, Accurate Reuse.”
When it came to naming spaces, Curtis stated:
“I love Gmail’s Compact, Cozy, Comfortable space toggle. So when we built our space system, I suggested we use those labels in our work.”
Notice how these names are relatable to the average person and how practical they can prove to be in day to day interactions: "Hey, can we change the spacing between these two buttons from Compact to Comfortable please?”
Naming schemes that are too technical or vague alternatively can be problematic.
Take for instance this scheme: single_spacing, double_spacing, triple_spacing, etc, where a spacing equates to 8dp.
Sure, one may be able to derive the actual quantity of DPs used per value, but the values themselves aren’t as memorable nor as outspoken as with the previous example. Think of also how limiting it would be to tie a name to its value. What if one were to change a value out of the many spacings, how would that be accomplished?
Find the balance between too granular and too general of values
Consider the example of spacings, which ought to have values for both vertical & horizontal use cases, and not only be generalized as spacings. The reason is, you'll be able to easily configure your apps' looks and feel depending on newer phone size trends.
Imagine phones got taller, but not any wider. Then simply increase your vertical spacing values, leave your horizontal values alone, and ta-da — you're done.
Text sizes defined alone would be considered too granular. Text appearances, however, are a better generalization that include: font, text size, and attributes applied, i.e. bold, italicized. This will tremendously simplify usage, however, require more upfront planning.
Colors directly referenced by name is not a good idea. Instead, create indirect reference of colors that allows for easier digestion:
Bad granular color naming:
Good general color naming:
Use platform specific design tokens first
Using out of the box values for your app will create more commonality with apps found on its respective platform, thereby creating more immediate familiarity with your users.
Both Android & iOS have text appearances out of the box for example:
Android has a theming system that allow you to set a number of colors that are then applied to your widgets app wide:
Define values against a single device
Since design tokens display differently from phone to phone, it's best to define values against a single phone for the optimal experience. Naturally choose the device that's most commonly used by customers. Once customers shift usage to a more popular phone, see if your values need calibration against it. If need be, adjust accordingly and repeat.
How to best communicate design tokens
Attributes for all
When documenting your design tokens, your goal should be to make them as easy to digest by both designers and developers as possible. Whatever attributes that either side find useful ought to be noted.
For example, say your colors are well named and have their hex values defined. Designers may like to note their HSL lightness to help better tell between those grays. Although this serves no use to developers, their inclusion brings no harm, thus preferred.
Narration via visualization
An IKEA catalog is nothing without its images. Similarly, inlining displays of design tokens in action makes your document that much more compelling and outspoken.
Close to home
The further away your documentation gets from the app and those who work on it, the more likely it is to be out of sync. How much closer can the document be to the app, than to be inside the app itself?
Not much, therefore design systems that are in-app are the way to go. What do I mean by in-app? Literally embedding a page that’s accessible to designers, PM, QA, and developers within the app that’s being developed itself, however inaccessible to customers.
“Is it really worth the hassle?” you may ask yourself. Consider this: it can act as a table of contents of the app’s used values for the reader, such as a QA, who can now ensure the table matches its contents. Furthermore, it can serve as a contract amongst team members to abide by. If a design mockup uses a value outside of the table of contents, then a discussion should ensue to whether this new value belongs to the system or not.
But wait, there’s more!
To help kick start your project’s design tokens, I've published a variety of values visualized for both Android & iOS! They’ve been released to the public domain making them entirely free in usage and modification.
Can software be beautiful? Certainly a great looking and intuitive interface which enables people using the app to accomplish their tasks with little effort and minimal friction could be called beautiful. Software developers are privy to another kind of beauty: The inherent beauty in well-constructed software that makes it easy for a software team to effortlessly integrate disparate pieces into a compound whole. Well-constructed software can be appreciated much the same way that a beautiful painting, a sculpture, a building or a piece of music can be appreciated.
But beautiful software is not necessarily great software. Ideally, great software is great because it empowers people. It can give them what could be described as superhero-like capabilities. We definitely want people to feel like superheroes when using our software, but we want them to identify more with Superman or Wonder Woman than with The Greatest American Hero. In other words, they should be able to achieve great things, but, unlike The Greatest American Hero’s Ralph Hinkley, they should not be rendered powerless without a sufficiently detailed instruction manual.
For software to empower people in this way, it must be designed from the ground up to be anticipatory. Great software often feels omniscient. It makes the difficult look easy, even though, ironically, making the difficult look easy is really quite hard. As Steve Jobs is said to have put it, “Simple can be harder than complex. You have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains.”
As software developers, we must also strive to anticipate the events and conditions our software may be forced to deal with if we wish to create great software. The wireframes or mockups we receive from designers tend to focus on the so-called “happy path”. These are the things that the people using our software will hopefully be doing most of the time, and they include such things as writing great novels, sending money to friends, depositing checks, or collaborating and communicating with colleagues. These concepts are the things people would mention when describing our software to others.
Other events require error handling and recovery. These are the things which result from software being used in the real world. They are expected, but, hopefully, infrequent. Network requests may fail. The device may run out of memory or storage capacity. Great software accounts for these scenarios and provides a fluid though perhaps degraded experience in spite of their presence.
Finally, there are exceptional events. These are failures from which we cannot recover programmatically, and include hardware failures or assumptions about external dependencies which have held true in the past but which have since changed and upon which we can no longer rely.
Software is best constructed by taking the existence of these types of scenarios into account from the beginning instead of “bolting them on” later. To me, great software must be robust by design.
The benefits of robust-by-design software
Software that is built from the ground up anticipating the various ways things can go wrong is more likely to be of the necessary quality and to deliver a rock-solid user experience. Robust-by-design software will also be less likely to crash or behave in an unexpected manner in the course of operation.
In addition, the resulting software will provide a better user experience. Things will be more fluid, and errors, when they undoubtedly occur, will be handled smoothly. The app won’t unexpectedly jump between screens or overlay elements from the anticipated “good state” with elements from the “error state”. They won’t show blank screens or display a spinner ad infinitum. Furthermore, it will be easier to avoid these unwanted situations.
The app will also be more secure as it will not crash as often or continue to operate in an unexpected state. The software will also safely clean up after itself in these situations (i.e., close open files or overwrite memory to remove sensitive information) thereby also increasing security.
The app will also be easier to maintain as the code will be better constructed. It will be less likely that other developers will cause software to regress as these scenarios will be more explicit in the code. The app will also be easier to test as it will be structured as a collection of components, thereby helping with separation of concerns.
Creating robust-by-design software requires us to think about as many of the various scenarios that we can to make sure we cover all the things which can go wrong. This is a skill that software developers must hone. Modern software is quite complicated, and there are often many things that can go wrong at any time. But, like any skill, one can get better at anticipating these scenarios. The more we practice this approach, the more scenarios will be known to us and the better we will become at thinking about new ones.
Why being a 'defensive pessimist' matters
I often tell my colleagues that I spend more than 90 percent of my time working to make sure the software I create handles those scenarios which occur less than 10 percent of the time. A lot of that time is spent trying to find those scenarios which are not on the happy path. Thinking of those scenarios can be hard, making sure the software is able to handle those scenarios well is easier (though not easy). Making sure the software operates well in the presence of those scenarios is made easier when the need to do so is taken into account from the beginning.
Obviously there’s no expectation or requirement that we think of every possible thing that can go wrong, but the more such scenarios we think of the better. It makes it more likely that the scenarios we had failed to think of may be covered by the scenarios of which we did think. Furthermore, any new scenarios will be easier to incorporate later as we already have support for alternate paths and do not need to bolt those on well into the development cycle.
Another way to say this is that, as software developers, we should think about our software through the lens of “defensive pessimism”. Defensive pessimism is a cognitive strategy whose practitioners work through all the things which could go wrong and plan accordingly. According to a New York Magazine article on defensive pessimism, while it might seem better to expect things to go well and not worry about negative outcomes, it most certainly is not better. According to research conducted by Dr. Julie Norem, a psychology professor at Wellesley College and a leading researcher of the defensive pessimism concept, defensive pessimists actually benefit from all the worrying they do as they approach situations more fully prepared.
That’s exactly what we want to do when developing software. We could be optimists, and assume that everything will work out okay, but we will quickly find that that’s unrealistic in practice. We could be pessimists and assume everything will always go wrong, but then we’d never write any useful software.
Instead, we should strive to be defensive pessimists who create beautiful and useful software that is robust enough to remain beautiful and useful when the inevitable happens and things go wrong.
Software which anticipates our next action can feel magical. As software developers, we can create a more solid foundation for our software and make it more likely to achieve that vaunted status if we work on anticipating all of the various scenarios it may have to deal with and incorporate that support from the beginning.
As the saying goes, the devil is in the detail. In other words, the details are from where that beauty comes. Getting these details right will make it more likely that the software we create is in fact great software.