Thursday, July 28, 2016
Wednesday, July 6, 2016
The phrase "what you see is what you get," from which the acronym derives, was a catchphrase popularized by Flip Wilson's drag persona Geraldine, first appearing in September 1969, then regularly in the early '70s on The Flip Wilson Show. The phrase was a statement demanding acceptance of Geraldine's entire personality and appearance. wikipedia
NINO - Natural-In, Natural-OutThe idea, though, is powerful. Being able to see what the output of your work looks like as you edit is a tremendous relief to the mental burden of creation. It was a hot idea in the '80s and '90s, but it is equally important, and often ignored, today in 2016.
- They visually get out of the way. There is less screen clutter to distract you.
- Their feature-set is restrained. They avoid presenting you with too many options. Instead, they are carefully designed to have the bare minimum essential tools you need to create great stuff.
Comparison: Paper by FiftyThree - a NINO App
Comparison: Microsoft OneNote - a very Un-NINO App
Sunday, June 12, 2016
Given two solutions to a problem, the one with less code is usually better.
Plite of the ProgrammerOur job as programmers is to deliver value to customers. We deliver value by identifying needs, translating them into requirements, and writing code to meet those requirements. The difficulty of the task is compounded by the fact that requirements are constantly, unpredictably changing. Even after we finally ship, the story isn’t over. Code is a living thing that must be maintained, usually well beyond anyone's expectations.
Over the lifetime of a product, we will edit code 10x more than we write code, and we will read code 10x more than we edit it. Each token we add to our code may be read over 100 times. Every token we save could save up to 100 token-thoughts and 10 future edits. The key to our productivity is writing less code.
Why Count Tokens?Tokens are the smallest meaningful element in code. Tokens are a more objective measure of code size since lines can have any number of tokens. Measuring tokens also ignores white-space and comments. Last, measuring tokens doesn't penalize using clear names. ‘Occupations’ is just as good a name under the token metrics as ‘occus’ or other hard to understand abbreviations.
Don't abbreviate words. Saving keystrokes only saves writing the code. It doesn't save edits or reading. Abdications make reading harder. Since reading code dominates our time, abbreviations are a losing proposition. Only use shortened words if the shortened version is used at least as commonly in speech.
Measuring tokens is a simple, effective metric that lets us make decisions quickly and get on with solving problems and delivering value.
Why ‘Write Less Code’?It's a simple concept with depth. Amateurs and masters both can apply and learn from it. A more accurate metric might be refactorability. We spend most of our time refactoring code, not writing it. Refactorability is the code-quality metric. It can be broken down into code size, clarity, and structure. Of the three, size is the only one that can be objectively measured, and while clarity and structure are important, both are usually improved by reducing code size. Refactorability is not something a novice will understand. ‘Write less code’ is an excellent guiding principle for all programmers.
How to Write Less CodeAll other good coding practices essentially reduce code size. Two of the most important, and most often violated coding practices for reducing code-size are DRY and ZEN.
DRYDon't. Repeat. Yourself. Don't you dare repeat yourself ;). The most problematic artifacts I've seen, both from novice and expert programmers, is code repetition. The big problem with repetition is it compounds the complexity of refactoring. Not only do we have to fix two or more things instead of one, but we have to understand how they all interact. Plus it bloats the code-base making it hard to understand.
DRY is a subtle art. The first, obvious level is ‘don't copy-paste your code,’ but as we level-up, we start to realize anything gzip might compress potentially violates DRY. The ultimate measure is, as always, refactorability. How many code-points need to change for a common refactor? Is there a way to reduce repetition to reduce the complexity of refactorability?
ZENBuild it with Zero Extra Nuts (more commonly known as YAGNI). Because it is impossible to predict future requirements, adding anything to our code that isn't strictly necessary to meet current requirements is not only a waste of time now, but it will haunt us for at least 10x future edits and 100x future reads.
It is fun to add cool features, but the master knows the only thing that matters is delivering value to the customer.
Write Less Code - Formalized
- Given two different functions, modules or programs
- that both meet or exceed the problem's requirements, both correctness and performance
- the one with less tokens is always better
- as long as it doesn't sacrifice clarity.
The Practice of Writing Less CodeAs with everything in life, writing less code is a practice. There is no point where we will master it. There is always another layer of deeper understanding. We are always learning how to make our code DRYer and more ZEN. We must constantly be looking for ways to meet requirements with less code.
Saturday, February 6, 2016
ZEN - Zero Extra Nuts. ZEN code is minimalist. It is relentlessly focused on solving exactly the requirements and nothing more. vs YAGNI: (3)
What is a Framework?
Why Do We Build Frameworks?
Are In-house Frameworks Worthwhile?
- Complexity before split: N2
- Complexity after split: 0.6 * N2
- App: (1.1 * N/2)2
- Framework: (1.1 * N/2)2
- Total: 2 * (1.1 / 2)2 * N2
When to use 3rd Party Frameworks
- Does it do what you need it to do?
- Does it meet your performance goals?
- Is the source open?
- Can you look at the source code? No matter how good the documentation is, there are always questions it doesn’t answer. If the source is open, you can get definitive answers. If not, you will be flying blind.
- Is it OpenSource?
- Can you contribute improvements back to the project?
- How clear are the maintainers about what sort of contributions are acceptable?
- Can you fork the project? This is only a last resort, but it is nice to have as an option. If you expect to fork early, you will be mostly maintaining your own, in-house framework. The problem with this is it is a codebase no-one in your organization knows well. Seriously consider writing your own in-house framework from the start.
- How difficult will it be to switch frameworks later?
- How much of your code will directly interact with the framework?
- If you are picking a UI framework, most of your code will be tied to that framework. Changing frameworks later probably means rewriting the app from scratch.
- If you are using an encryption framework, like, say, md5, only a line or two of your app will use it. Changing that framework later is usually trivial.
- Momentum. Usually there are multiple options for the same type of framework. Eventually, some die out and some thrive. It’s a good idea to use a tool like Google-Trends to determine which projects are thriving and which are dieing. If a framework dies, you may need to fork it to maintain it, and then you are back to maintaining an in-house framework.
- Direction. 3rd party frameworks evolve outside your control. It is important to not only assess the current technical merits of the framework, but also, where is the framework going? What values and goals does the controlling team have? What values and goals does their organization/funding have? If your use-case is not squarely in their target use-cases, seriously consider looking elsewhere.
When to Write an In-House Framework
- Is it the best of modules?
- Is the interface simple?
- Will the implementation be well isolated and minimally leaky?
- Is there a reasonable chance you’ll reuse the framework on other projects? ZEN argues you should be cautions making assumptions here, but if you think there is a > 90% chance you’ll reuse it even once, this can be a big factor.
Frameworks Clarify ThinkingFrameworks have another benefit beyond reducing complexity. Once you have isolated part of your code in a framework it takes on a life of its own. It has purpose beyond just serving the current app (though it should still be driven by that app's requirements ala ZEN). A framework begs for clarity in its purpose. By drawing a line between your app and your framework you have to start thinking clearly about what belongs where.
Don't expect to nail the framework's "purpose" in the first pass. Your framework will evolve as ZEN drives it. Over time, though, clarity will emerge and you will have a new, powerful tool, codified in your framework, but also in your mental toolbox for solving and thinking about programming problems.
Writing Frameworks is Hard - and WorthwhileI don't want to make this seem easy. Writing the best of all possible modules is hard! However, it is a learnable skill. You are only going to learn a skill be practicing it - a lot.
And what about ZEN? Writing frameworks and ZEN are not in conflict. You can write frameworks while observing ZEN. After all, DHH, one of the strongest proponents of ZEN, wrote Ruby on Rails.
- I measure codebase size in parse tokens rather than lines of code. Though still only an approximate measure, they are much better than LOC. They are the smallest meaningful unit in code. LOC measures several aspects of code which are ignored by the compiler including comments and whitespace.
- Codebase complexity can be understood in terms of graph-theory. Complexity comes from the number of possible interactions within the code. In the worst case, if you have N bits of code (tokens), you can have as many as N * (N - 1) or roughly N2 possible interactions. In practice the relationship between code-size and code-complexity is somewhere between O(Nk>1) < CodeComplexity(N) < O(N2).
Modular design is all about reducing the number of interactions a chunk of code has with the rest of the code-base. This is how modules help reduce complexity.
- ZEN is roughly the same concept as YAGNI, but unlike the latter, both the word 'zen' and the expansion, 'zero extra nuts (and bolts)' convey meaning. We can say some code needs to be more 'zen,' and others will understand. To say code needs to be more 'yagni' holds no meaning for most people.
Saturday, July 5, 2014
Video or Blog
de·sign (verb) \di-ˈzīn\Everything built or planned is designed. Putting forethought into something is designing. The difference isn't whether or not something is designed but rather how well designed it is — how much forethought was put into it.
to plan something in your mind
more with less — Start with the handle. It is tapered so people with different sized hands can find a comfortable grip. Next, notice how it supports pouring. Its long tapered spout makes it easy to pour precisely. It even excels at the simple task of holding water. Being a single plastic mold it is unlikely to ever spring a leak. The lightweight plastic ensures that even with a small amount of water and a tapered base it is not very tippy. The design also minimizes production costs. It allowing Ikea to sell it for an amazing 99 cents and as a bonus, they stack.
emotional — Beyond function, it is beautiful. The lines are graceful. The shape is alluring. It makes you want to pick it up and feel it.
compelling first impression — The app starts with a light, playful soundtrack. The screen then folds into an oragami panda. The music chreshendoes as we pans to a whole pack of pandas and the app's welcome screen. Tap "start" and the soundtrack morphs to a softer, pleasent background piece. Up until this point everything has been in black and white. A three second shuffling-card-slideshow of full-color animals transitions you into the app's home-screen.
beautiful, pervasive aesthetic — They brought a sense of elegance by integrating the origami theme. The theme is echoed at all levels of the app from the opening sequence to the sharing UI. Even the 3D globe appears to be made out of paper. The app's primary color palette is shades of grey. This makes the color portions of the app, such as the vividly colorful photos of the animals, stand out dramatically.
strategic — Charities often fail to clearly communicate why we should care. They are often too pushy, full of doom and gloom and ladened with guilt. This amazingly well designed app has none of those shortcomings. The majority of the app is about praising the majesty of the animals. It is inspiring and uplifting. It is anything but pushy. To even see the donation screen, you have to "unlock" the last animal ensuring the user is deeply engaged before asking for money.
holistic excellence — This is a highly focused product. The goal is wireless, high-quality sound, simplicity and style. Individually these are goals any portable sound system might target, together with Jambox's flawless execution elevates the product to another level. It invites everyone to take off their headphones and share their music.
differentiated — Balance uses a unique set of fonts setting it apart from other apps, and the one fancy 3D transition manages to not be distracting and furthers its differentiation.
empathic — The elegance of the interface is a brilliant bit of design, but the true genius of Nest is what happens behind the scenes. It tracks every time you set the temperature and automatically learns your daily routine. It automatically programs itself and soon it starts adjusting the temperature for you according to your past preferences.
Extreme focus takes what used to be a heinously painful task of programming your thermostat and transforms it into an effortless and joyful interaction.
Amazingly Great Design Defined
a·maz·ing·ly great de·sign (noun) \əˈmeɪzɪŋl'ē grāt di-ˈzīn\
Design that exceeds expectations down to the last detail.
Three Pillars of Amazingly Great DesignFocus, details and tools are essential for amazingly great design. They can take a lifetime to master, but even a novice can make use of them immediately. With these basic ideas and a lifetime commitment to learning and improving their application, anyone can become a great designer.
First Pillar: Focus
Time is your most valuable resource. Focus is the ultimate time management tool. Focus means learning how to use every moment of time for only the single most important thing you can do with it. Say 'no' to everything else.
customer archetypeThe first thing to focus on is your customer. Instead of describing the average or most common customer, I recommend inventing a customer archetype. Your archetype describes a potentially real person. An archetype is like an average person, but there is difference. Your average customer may have 2.5 children. The archetype forces you to choose a real mom with, say, exactly 2 children. With that choice, you can achieve amazingly great design for moms with 2 children instead of merely good design for moms of 2 or 3.
use-story archetypeWhen the customer interacts with your product you are guiding them down a specific designed path. This path has a story. It has a beginning, middle and end. In the beginning the customer has a task they want to accomplish. They must decide to use your product and take action to begin their journey. In the middle they are working on the task. This is where they spend the most time with your product. By the end they have accomplished the task. They are rewarded not only by the desired result, but also some set of positive emotions. The very best stories have excellent beginnings, middles and endings. They are just the right length. You certainly don't want your story to be too long, but you also don't want it to be too short. Write down the archetypical story for your product, step by step, with storyboards. This is a single linear path through time. Think of it as a movie rather than an interactive product. Focus on this single story exclusively, and making it the best possible story it can be.
singular focusThis singular focus on one customer and one story ultimately leads to a better product. A highly focused product is easier to use. The product itself can communicate to the customer what it is for and how to use it. The product tells its own story. Another benefit of a highly focused product involves human perception. Our minds are tuned to notice things that stand out. Doing one and only one thing amazing is better than doing many things merely "good." An amazing product will be cherished and remembered. A merely good product will be quickly replaced and forgotten, even if it does more.
time = features * qualityIn the end, Focus is the key to solving this equation. The time required to complete a project is proportional to the product's features and its quality. All too often people assume the feature-list is a hard requirement. If they have to meet a certain deadline, then quality has to be sacrificed. This decision always results in a mediocre product. Instead, if you want to make amazingly great products, then quality must be fixed a maximum. To meet a deadline, then, it is the feature list which must be culled. As you practice this methodology of extreme focus you'll find there are very few features which are requirements. As Jobs said, focus is about saying "no." To produce with maximum quality, keep saying "no" to features until the list is so short every last one of them can be implemented with excellence. The result will be a far better product.
Second Pillar: Details
The question then becomes, what details matter? This is a question which takes a lifetime to master. The first step is to learn how to broaden your scope. To inspire you, I'm going to cover four of the many types of details that might be important to consider when designing your product.
- Where is the product used?
- Is it loud or quiet, bright or dark?
- Who is around?
- What time of day will it be used?
productAssuming the product is some sort of application or website:
- Are all elements aligned exactly?
- Is there adequate white-space to make the viewer comfortable?
- What colors are used and are they used consistently?
- Is the app perceived to be performant and immediately responsive?
- Do the animations reduce distractions or are they themselves distracting?
- Are the fonts legible? Do they invoke the right emotional response?
- How are errors handled?
- What is their day like?
- Who are the important figures in their life?
- What social groups do they belong to?
- What are their hopes and desires?
- What will the person be thinking just before they use the product? Just after?
- Will they be thinking about the product while not using it?
- What do we want them to feel when they use the product?
- How will our customer want to be perceived while using our product publicly?
- How will the customer learn about the product?
- Where will they first see it?
- Where will they first "touch" it?
- When is their first real engagement?
- What is their daily engagement?
- What is their last engagement?
- How does the product reoccur in their thoughts after their last engagement?
- What details will help to reengage the user with this or other products?
Third Pillar: Tools
"Nothing is original. Steal from anywhere that resonates with inspiration or fuels your imagination. Devour old films, new films, music, books, paintings, photographs, poems, dreams, random conversations, architecture, bridges, street signs, trees, clouds, bodies of water, light and shadows. Select only things to steal from that speak directly to your soul. If you do this, your work (and theft) will be authentic. Authenticity is invaluable; originality is non-existent. And don’t bother concealing your thievery - celebrate it if you feel like it." - Jim JarmuschThe third and final pillar of great design is your idea toolbox. These are the tools and patterns you use to create the product and exceed expectations in the details. A designer's toolbox is constantly expanding and evolving. The best designers make a continual effort to improve it by all means available.
notebookKeep a design notebook. As you start noticing good and bad design in the world, start taking notes. This helps you clarify your thinking on the design and gives you something concrete to come back to when you need it.
opinionDevelop a well-considered opinion. In order to be a great designer you need to learn to care deeply about great design. You need to be able to not only distinguish between good and bad design, but also articulate why it is so. Be prepared to offend people. If you don't, then you aren't pushing the envelope.
playConstantly experiment with your tools. Free yourself of the constraints of your real projects and allow yourself to explore freely to discover great new possibilities.
inspirationCreativity is equal parts experimentation and inspiration. You need to constantly feed your brain new stimulus from the outside world. This includes trying out competitors products, but it also includes getting inspiration from completely different fields. Visit great works of art and architecture. Read voraciously, explore nature, take classes, go to conferences, read blogs and listen to podcasts.
Designer's AmnesiaIn addition to the three pillars, I have one important word of caution. The processes of design and implementation unavoidably leads to the designer memorizing the design. Any design, good or bad, can become "intuitive" to anyone who memorizes it. One loses objectivity and empathy for new users the more one uses a product, and it's worse if you are the designer.
Keep the following questions in mind:
- Is your focus the right one?
- Are there failures in details you can no longer see because you've memorized them?
- Is there a tool that obviously solves a problem better but you can no longer see it?
Impact of Amazingly Great DesignMany companies are committed to amazingly great design including Apple, Herman Miller, Blizzard, Jawbone, 53 and IKEA. Each of these companies have been successful largely because of their great design.
businessperceived value — Repeatedly exceeding expectations dramatically increases the customers perception of your product's value. You can charge more, customers will seek you out and you will stand out amongst the competition.
brand — Great design creates good will towards your brand. It is one of the most effective ways to show your customers you care about them. They will, in turn, begin to care about your brand and even come to love it.
actual value — Great design adds real, tangible value for the customer. Historically design has been considered window dressing - a frivolous veneer on the product which may sell 10% more. Thankfully, it is now clear that great design dramatically increases the value for the customer, and here's why.
customertime — Great design saves time. Just as time is the designers ultimate resource, it's also our customer's most important asset. All great design takes the customer's time into account and gives them the most bang-per-second.
reduced stress - Great design reduces stress and fatigue. Rough edges both literally and metaphorically wear us down and suck our energy. A poorly design product may get the job done, but we'll be emotionally and physically exhausted after using it. Instead, an amazingly designed product could actually energize, excite and slingshotting us to the next task of the day.
beauty and delight - Great design brings beauty and delight to our lives. Great design goes beyond the veneer of frivolous window dressing. Its beauty reaches deep inside the product and impacts us on many levels. It can inspire, sooth and bring joy. It can even impact us when we are not using the product. These positive emotions impact the bottom line for everyone. We are more productive under their influence and happier in life.
Zen of Amazingly Great DesignEach of the three pillars of great design is a never ending path towards mastery. We are constantly inventing and discovering new tools. There is always the next layer of details to consider, and a good designer is constantly refining their ability to separate the important from the unnecessary.
focus — Say "no" to everything but the most important features. Practice deep empathy with the customer to identify those essential features. Reduce the scope of the project until there is enough time to implement every aspect with excellence. Paradoxically, reducing a products features usually results in a better product.
details — Train your mind to be precise and attentive. Learn to see products from every angle and see every minute flaw. Discovering what details matter is equal parts science and experience gathered over a lifetime.
tools — As you progress you will learn thousands of tricks, patterns and solutions you can employ to implement your design. Each time you finish one design you'll have new and better ideas for the next one.
Overall, the key to becoming an amazingly great designer is to be aware of these pillars, follow your own passion and keep an open mind. Insight can come from the strangest places.
Sunday, December 15, 2013
The Visibility Problem
We have a problem in programming. The majority of our work is invisible. It's invisible to the end user. It's invisible to us. We can only see ~50 lines at a time of the thousands and millions of lines of code in our programs. Imagine a miopic Leonardo da Vinci who could only focus on a square inch of canvas trying to paint the Mono Lisa or even the Sistine Chapel.
Most modern debuggers can only show a dozen variables and a stack trace. Generously, that represents no more than a few hundred bytes of memory. Our running programs are measured in megabytes if not gigabytes. In anything but the most trivial program, we can't see more than a small fraction of a percent of our paused runtime state. When our creation is actually running, we are blind.
Two Challenges of Programming
All difficulties in programming can be separated into two categories. There are the problems due to core computer-science limitations or limitations of our personal understanding. These are legitimate challenges which require real engineering, design and exploration. All other problems are due to a lack of understanding of what our creation is actually doing.
One way to measure a programmer's skill is how well they can simulate programs in their head. This can be measured concretely by how much code can they write without error without running or compiling. Mental program simulation is the only way we can mange the complete lack of visibility in running programs. The best programmers have developed an intuitive sense about running programs over years and decades.
Simulating programs in our head is a major part of modern programming. This is broken. The computer is infinitely better at running programs. There is a monumentous opportunity to improve programming by developing better tools for inspecting, exposing and making our running programs transparent.
The Principle of Exposure and Transparency (POET)
POET: All bugs are trivial once their cause is exposed; given enough runtime transparency, all bugs are trivial.
The vast majority of bugs only require a few lines to fix. Most of our debugging time is spent trying to understand bugs well enough to know what two lines to change. POET embodies this observation: All this wasted time can be reclaimed with better instruments for understanding our running programs.
Given enough eyeballs, all bugs are shallow. - Eric Raymond, The Cathedral and the Bazaar
POET is a generalization of Linus's Law. Getting more people looking at the code - "enough eyeballs" - is one way to better expose the code's runtime properties. However, it is a very inefficient method. It is akin to saying "with enough miopic da Vincis, we can paint the whole Mono Lisa." While perhaps true, a better solution would be repair his vision so Leonardo can do it without assistance.
- Pay attention the next time you run your code. Why are you running it? What information are you attempting to gain? How much time does it take to gather this information? Be sure to include the time it takes you to context switch, type in commands, wait for the run to start and do whatever interaction it takes to bring the program to the required state. How might you gain that information quicker with better tools? LiveReload plugins for web-page development is one such example.
- When you are working on a bug or performance problem, note how much time you spend understanding the problem vs how many lines of code were changed in the final fix. If you could send that patch back in time, how much time would you have saved? Note the key insight along your discovery path led to the final solution. How could you have gotten that insight sooner? ( Spark Inspector was just that tool for us in a recent debug jam session for our iPad app. )
Wednesday, October 9, 2013
I changed one line in my text-layout code to be compatible with immutable rectangles:
- metrics.area.location = metrics.area.location.neg.add offset + metrics.area = rect metrics.area.location.neg.add(offset), metrics.area.sizeI can tell you there were no bugs in the new immutable Rectangle class.
Can you spot the bug?
There is no bug. The new line is correct, and yet that's all I changed.
It turns out I originally had a bug due to a mutation I wasn't taking into account, but that mutation made the layout algorithm work. When I stopped mutating the rectangle object, the "bug" stopped making the algorithm work. The reason it took me hours to find this bug was the new code was "right", but the algorithm was wrong.
Here's what was actually wrong, in 3 code snippets (CoffeeScript):
1) The original code that worked but had an accidental mutation:
updateTextLayout: -> offset = point() @area = @metricsList.area # object assigned here for metrics in @metricsList metrics.area.location = metrics.area.location.neg.add offset # gets mutated here the first time through the loop offset = offset.add 0, @fontSize @area = @area.union metrics.area @size = @area.size2) Code with one line changed that seemed correct but didn't work:
updateTextLayout: -> offset = point() @area = @metricsList.area for metrics in @metricsList metrics.area = rect metrics.area.location.neg.add(offset), metrics.area.size # @area no longer gets mutated offset = offset.add 0, @fontSize @area = @area.union metrics.area @size = @area.size3) Final working code:
updateTextLayout: -> offset = point() @area = null # FIX - don't capture the wrong value here for metrics in @metricsList metrics.area = rect metrics.area.location.neg.add(offset), metrics.area.size offset = offset.add 0, @fontSize @area = if @area then @area.union metrics.area else metrics.area # FIX - capture the right value here @size = @area.size