tag:blogger.com,1999:blog-25335547594589236212024-03-21T13:31:51.177-07:00Essence and ArtifactSeparating the Essencial from the ArtificialShane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.comBlogger31125tag:blogger.com,1999:blog-2533554759458923621.post-20435776007560973192019-07-10T10:17:00.001-07:002020-09-20T21:27:35.262-07:00The Master Developer's Path: Productivity<p>
I recently did a talk at <a href="http://www.genui.co">GenUI.co</a> on how to increase your development productivity through self-awareness and incremental improvement. Below is a teaser. The full article, and presentation video, is here: <a href="https://www.genui.com/resources/developer-productivity-guide">genui.com/resources/developer-productivity-guide</a> (free, no-ads, enjoy!)
<h3>Defining “Mastery”</h3>
<p>I studied Japanese in college and one phrase that stuck with me is: “chiri mo tsumoreba yama to naru” — “Even dust, if piled up, can become a mountain.” Mastery is the result of small, incremental, and directed improvements over time. I want to share some ideas on how you, throughout the normal workday, can make these incremental improvements and take steps on the path toward mastery.
<p>Counting my teenage years, I have been a developer for almost three decades. I can offer some concrete insights, learned over those years, but most of all, I offer you a philosophy on how to be a self-improving developer. And while I’m addressing developers, I do think much of this applies to designers – in both cases, it's about creating something new that has never been seen before.
<p>Here's just one of the many insights from my talk:
<blockquote>“You can ship any project on-time, under budget, <br>and with quality … You just have to cut features.”</blockquote>
<p><b><a href="https://www.genui.com/resources/developer-productivity-guide">Read the full article or watch the 34 minute presentation here</a></b>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com262tag:blogger.com,1999:blog-2533554759458923621.post-82721025555272407052018-02-09T14:47:00.001-08:002018-02-09T14:47:18.026-08:00CaffeineScript<span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;">I believe less is more. It is the first principle of design and the foundation of just about every good programming practice: </span><a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="nofollow" style="background-color: white; box-sizing: border-box; color: #0366d6; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; text-decoration-line: none;">DRY</a><span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;">, </span><a href="https://en.wikipedia.org/wiki/KISS_principle" rel="nofollow" style="background-color: white; box-sizing: border-box; color: #0366d6; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; text-decoration-line: none;">KISS</a><span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;">, </span><a href="http://www.essenceandartifact.com/2016/02/yagni-and-building-in-house-frameworks.html" rel="nofollow" style="background-color: white; box-sizing: border-box; color: #0366d6; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; text-decoration-line: none;">ZEN (YAGNI)</a><span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;">, </span><a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" rel="nofollow" style="background-color: white; box-sizing: border-box; color: #0366d6; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; text-decoration-line: none;">single responsibility principle</a><span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;">, </span><a href="https://en.wikipedia.org/wiki/Interface_segregation_principle" rel="nofollow" style="background-color: white; box-sizing: border-box; color: #0366d6; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; text-decoration-line: none;">interface segregation</a><span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;">, etc... That's why I wrote CaffeineScript. This info-graphic shows the result:</span><br />
<span style="background-color: white; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://raw.githubusercontent.com/wiki/shanebdavis/caffeine-script/Why-CaffeineScript-InfoGraphic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="398" height="640" src="https://raw.githubusercontent.com/wiki/shanebdavis/caffeine-script/Why-CaffeineScript-InfoGraphic.png" width="318" /></a></div>
<div style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px;">
<br /></div>
<div style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px;">
CaffeineScript, with the help of ArtSuite, takes <span style="box-sizing: border-box; font-weight: 600;">3x</span> less code to write this complete implementation of Tic-Tac-Toe. In general, CaffeineScript is <span style="box-sizing: border-box; font-weight: 600;">2.5-3x</span> more efficient than JSX, TypeScript or JavaScript. Imagine seeing 3x as much code on screen at once. Imagine having 3x less code to write. Imagine having 3x less code to change when you need to refactor. Imagine having 3x less code to debug.</div>
<div style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px;">
TicTacToe source:</div>
<ul style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px; margin-top: 0px; padding-left: 2em;">
<li style="box-sizing: border-box;"><a href="https://github.com/imikimi/art-suite-demos/blob/master/source/Art.SuiteDemos/Demos/TicTacToe/Main.caf" style="box-sizing: border-box; color: #0366d6; text-decoration-line: none;">CaffeineScript source</a></li>
<li style="box-sizing: border-box; margin-top: 0.25em;"><a href="https://github.com/imikimi/art-suite-demos/blob/master/source/Art.SuiteDemos/Demos/TicTacToe/TTT_react_comparison.jsx" style="box-sizing: border-box; color: #0366d6; text-decoration-line: none;">React/JSX combined source</a></li>
<li style="box-sizing: border-box; margin-top: 0.25em;"><a href="https://reactjs.org/tutorial/tutorial.html" rel="nofollow" style="box-sizing: border-box; color: #0366d6; text-decoration-line: none;">React/JSX tutorial</a></li>
</ul>
<div style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px;">
TicTacToe live:</div>
<ul style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px; margin-top: 0px; padding-left: 2em;">
<li style="box-sizing: border-box;"><a href="http://imikimi.github.io/art-suite-demos/?demo=TicTacToe" rel="nofollow" style="box-sizing: border-box; color: #0366d6; text-decoration-line: none;">ArtSuite/CaffeineScript on github</a></li>
<li style="box-sizing: border-box; margin-top: 0.25em;"><a href="https://codepen.io/gaearon/pen/gWWZgR?editors=0010" rel="nofollow" style="box-sizing: border-box; color: #0366d6; text-decoration-line: none;">React/JSX on codepen</a></li>
</ul>
<div style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px;">
Of course, just because CaffeineScript can reduce code-size by 3x doesn't mean you'll be a full 3x faster. CaffeineScript cannot reduce the essential logic of your code. However, it dramatically cuts back the noise so you can see your core logic clearly.</div>
<div style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px;">
More reading:</div>
<ul style="box-sizing: border-box; color: #24292e; font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; margin-bottom: 16px; margin-top: 0px; padding-left: 2em;">
<li style="box-sizing: border-box;"><a href="http://caffeinescript.com/">CaffeineScript.com</a></li>
<li style="box-sizing: border-box;"><a href="http://www.essenceandartifact.com/2016/06/write-less-code.html" rel="nofollow" style="box-sizing: border-box; color: #0366d6; text-decoration-line: none;">Writing Less Code</a></li>
</ul>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com23tag:blogger.com,1999:blog-2533554759458923621.post-25261368208143764732017-08-15T11:57:00.000-07:002017-08-15T13:16:05.495-07:00ArtAtomic - 2D Geometry and Color library for JavaSript<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1oMoWCIjNbmMIuP2Y6DpPGB_MK3znU2V3DMZo4CZFw6Wm0RNARtJPUycdXO2p1Log1c4h-OMC26VWHS3ofMwNvAcikKWPrNxs-3qxXp564qi91od0S5eopCbzXfznMmzLmscEU6pBnPDZ/s1600/IMG_0780.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="503" data-original-width="1600" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1oMoWCIjNbmMIuP2Y6DpPGB_MK3znU2V3DMZo4CZFw6Wm0RNARtJPUycdXO2p1Log1c4h-OMC26VWHS3ofMwNvAcikKWPrNxs-3qxXp564qi91od0S5eopCbzXfznMmzLmscEU6pBnPDZ/s400/IMG_0780.jpg" width="400" /></a></div>
<br />
When doing 2D graphics there are a few patterns you'll use all the time - points, rectangles, matrices, etc... To make 2D geometry and colors easy to work with, use <a href="https://github.com/art-suite/art-atomic" target="_blank">ArtAtomic</a>. The atomic data-types include: Point, Color, Matrix, Rectangle and Perimeter. ArtAtomic provides the foundation for other ArtSuite libraries including ArtEngine, ArtText and ArtBitmap.<br />
<div>
<br />
<h2>
Quick Example</h2>
</div>
<div>
(in <a href="http://caffeinescript.com/">CaffeineScript</a>)</div>
<div>
<pre>p1 = point 10, 20
offset = point 300, 400
area = rect 200, 200, 1000, 500
area.contains p1 # false
area.contains p1.add offset # true!
red = rgbColor #f00
blue = red.withHue 2/3
white = red.withSat 0
red2 = hslColor 0, 1, 1
red3 = hslColor 1, 1, 1
red2.eq red # true!
red3.eq red # true!
halfTransparentRed = rgbColor #f007
halfTransparentRed.eq red.withAlpha .5 # true!
</pre>
<br /></div>
<h2>
What Does Atomic Mean?</h2>
These classes are designed to be used in a pure-functional way. Never modify their properties. Instead, use their methods to generate new objects.<br />
<br />
HOWEVER, JavaScript performance requires minimizing the number of objects you create. As-such, there are some ways to end-run the pure-functional nature of ArtAtomic by re-using existing same-type objects. This should only be done in places where you can prove that there are no other references to the object you are reusing. In general, the way this works in ArtAtomic is some methods take an extra, optional argument called "into" which lets you specify where the result should be placed. If that argument is not provided, "into" is set to a new object. In either case, "into" is the value returned from these functions.<br />
<br />
<h2>
Color (primary props: r, g, b, a)</h2>
<div>
The Color class provides many tools for manipulating colors. It works in RGBA and HSLA color-spaces. It supports converting to and from many standard string-formats: "#FFF" and "rgb(255, 255, 255)" for starters. </div>
<div>
<br /></div>
<div>
One simple, cool example: rgbColor("#f00").withHue(2/3) == "#00f"</div>
<div>
<br /></div>
<h2>
Point (primary props: x, y)</h2>
<div>
Points are the foundation of any geometry framework. These points are all 2D: x & y. This library lets you perform math and comparisons on points: point(1, 2).add(point(3,4)).average(). You can treat these points as vectors: dot and cross-products are: point1.dot(point2) or point1.cross(point2). Also, point2.magnitude will return the magnitude of a point.</div>
<div>
<br /></div>
<div>
<h2>
Rectangle (primary props: x, y, w, h)</h2>
</div>
<div>
Rectangles specify their upper-left-hand corner and their width and height. Strictly speaking, the upper-left point is included in the rectangle and the lower-right point is not: rect(1,2,3,4).contains(point 1, 2) - true, but rect(1,2,3,4).contains(point 4, 6) is false.</div>
<div>
<br /></div>
<div>
Rectangle has many useful methods in addition to basic arithmetic and comparison including: union, intersection, cutout, nearestInsidePoint and more...</div>
<div>
<br /></div>
<div>
<div>
<h2>
Matrix (primary props: tx, ty, sx, sy, shx, shy)</h2>
</div>
</div>
<div>
This 2D matrix library provides all the standard matrix operations: translate, scale, rotate, mul(tiply), invert and, most importantly, myMatrix.transform(myPoint) => myTransformedPoint. </div>
<div>
<br /></div>
<div>
<div>
<h2>
Perimeter (primary props: left, right, top, bottom)</h2>
</div>
</div>
<div>
The most recent addition to ArtAtomic is Perimeter. This is primarily used to express margins and padding in ArtEngine. Currently there are only a few additional methods on top of the standard arithmetic and comparison operations.<br />
<br /></div>
<div>
<h2>
ArtAtomic Resources</h2>
<div>
Learn more on the wiki: <a href="https://github.com/art-suite/art-atomic/wiki">ArtAtomic Wiki</a></div>
<ul>
<li>github: <a href="https://github.com/art-suite/art-atomic">github.com/art-suite/art-atomic</a></li>
<li>npm: <a href="https://www.npmjs.com/package/art-atomic">npmjs.com/package/art-atomic</a></li>
<li>install: <span style="font-family: "courier new" , "courier" , monospace;">npm install art-atomic</span></li>
</ul>
</div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com8tag:blogger.com,1999:blog-2533554759458923621.post-6194605622277616972017-03-20T08:08:00.001-07:002017-04-26T06:47:21.495-07:00Programming Principles & Best Practices Reference<div>
Here is my quick reference to the most important programming principles, best-practices and acronyms.<br />
<b><br /></b>
<br />
<div style="margin: 0px;">
</div>
<ul>
<li><b>DRY</b> - <a href="http://www.essenceandartifact.com/2016_06_01_archive.html" target="_blank">Don't Repeat Yourself</a></li>
<li><b>EVA</b> - <a href="http://www.essenceandartifact.com/2011/03/essence-and-artifact-design-principle.html">Essence Vs Artifact</a></li>
<li><b>KISS - </b><a href="https://en.wikipedia.org/wiki/KISS_principle" target="_blank">Keep it Simple, Stupid</a></li>
<li><b>NINO</b> - <a href="http://www.essenceandartifact.com/2016/07/nino-beyond-wysiwyg.html">Natural-In, Natural-Out</a></li>
<li><b>POET</b> - <a href="http://www.essenceandartifact.com/2013/12/principle-of-exposure-and-transparency.html">Principle of Exposure and Transparency</a></li>
<li><b>POLS</b> - <a href="https://en.wikipedia.org/wiki/Principle_of_least_astonishment" target="_blank">Principle of Least Surprise</a></li>
<li><b>SOUP</b> - <span style="font-family: "helvetica neue"; font-size: 14px;"><a href="http://www.essenceandartifact.com/2017/01/soup-showing-our-undies-vs-conscious.html">Showing Our Undies Programming</a></span></li>
<li><b>WLC</b> - <a href="http://www.essenceandartifact.com/2016/06/write-less-code.html">Write Less Code</a></li>
<li><b>ZEN</b> - <a href="http://www.essenceandartifact.com/2016/02/yagni-and-building-in-house-frameworks.html">Zero Extra Nuts</a></li>
</ul>
</div>
<div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Times; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<div>
</div>
</div>
</div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com197tag:blogger.com,1999:blog-2533554759458923621.post-24893193324812556652017-01-28T08:54:00.002-08:002017-06-01T21:33:24.900-07:00Your SOUP is Leaking - Crafting Acronyms<h3>
<div style="font-size: medium;">
<span style="font-size: small;"><span style="font-weight: normal;">I've been making a lot of acronyms lately. Acronyms can help us think about, remember and communicate a concept. A good acronym, like a good word, can fundamentally change the way we understand the world. </span></span><br />
<span style="font-size: small; font-weight: normal;"> </span><br />
<span style="font-size: small; font-weight: normal;">Until recently, civilization didn't have a word for </span><span style="font-size: small;"><span style="font-weight: normal;">blue</span><span style="font-weight: normal;">. It's true! </span><a href="http://www.businessinsider.com/what-is-blue-and-how-do-we-see-color-2015-2" style="font-weight: normal;" target="_blank">Business Insider</a><span style="font-weight: normal;"> has a surprisingly good article about how no ancient civilization had a word for blue. Even more surprising, it might be true that civilizations without a word for blue couldn't even see blue - at a conscious level. They had the same hardware, but their software wasn't tuned to thinking about blue, and therefor they couldn't see it. </span></span></div>
<span style="font-size: small;"><span style="font-weight: normal;"><br /></span></span>
<span style="font-size: small;"><span style="font-weight: normal;">Words enable thinking and communicating. Without the word blue, how would you describe the color? You might say "it's the color of the sky," but as the lovely children's book </span><a href="https://www.youtube.com/watch?v=noNTx4YdgMY" style="font-weight: normal;" target="_blank">Sky Color</a><span style="font-weight: normal;"> demonstrates, the sky has colors across the spectrum. You might point to other blue things, but it turns out in ancient cultures basically there weren't any blue things. Blue is extremely rare in nature, and no-one is going to build something they don't have a concept of.</span></span></h3>
<div>
<span style="font-size: small;"><span style="font-weight: normal;"><br /></span></span></div>
<h3>
<span style="font-size: small;"><span style="font-weight: normal;">Concepts are powerful. Concepts embodied in a word, more-so.</span></span></h3>
<div>
<br /></div>
<h3>
Picking a Good Acronym</h3>
<h3>
<span style="font-size: small;"><span style="font-weight: normal;">Really, we are talking about making up a good word or a good, new-use of a word for a concept. Acronyms work because they provide a built-in </span></span><span style="font-size: small; font-weight: normal;">mnemonic for remembering them. I find the stickiest acronyms reuse existing words such that the other meanings of that word somehow reinforce the new concept.</span></h3>
<div>
<span style="font-size: small; font-weight: normal;"><br /></span></div>
<div>
<span style="font-size: small; font-weight: normal;">Traits of a good acronym:</span></div>
<div>
<ul>
<li><b>Pronounceable</b> - if you want people to use it, they have to be able to say it</li>
<li><b>Real Word</b>, preferably with related meaning - the stickiest acronyms use this (see above)</li>
<li><b>Fun or Funny</b> - make it playful so people play with it - and start using it</li>
<li><b>Phonetic</b> - if it isn't a real word, make sure it's a least phonetic. If someone hears it, they should be able to write it down without having it spelled out.</li>
<li><b>Short</b> - shorter == stickier</li>
<li><b>Clear Expansion</b> - the expansion should be clear and succinct. It should embody the essence of the new concept.</li>
<li><b>Try not to Force Letters</b> - sometimes the expansion is 'forced' to match the acronym. Letters are left out or added to make it work. The more forced, the less sticky. </li>
</ul>
<div>
<br /></div>
<h3>
My Favorite Case Study</h3>
<div>
<b><br /></b></div>
<div>
<b>DRY</b> - <a href="http://www.essenceandartifact.com/2016_06_01_archive.html" target="_blank">Don't Repeat Yourself</a></div>
<div>
<ul>
<li>Real word</li>
<li>Super clear expansion</li>
<li>Real-world wet vs dry makes a nice analogy between code with and without repetition respectively.</li>
<li>When I first ran across DRY maybe 7 years ago, I went "Yeah!!! Someone summed up a vague concept in my head succinctly and clearly!" Ever since it's become my daily mantra and a significant influence in my ever-deepening understanding of programming.</li>
</ul>
<div>
<br /></div>
</div>
<h3>
My Acronyms</h3>
</div>
<div>
<b><br /></b></div>
<div>
<!--?xml version="1.0" encoding="UTF-8"?-->
<b>ZEN</b> - <a href="http://www.essenceandartifact.com/2016/02/yagni-and-building-in-house-frameworks.html">Zero Extra Nuts</a></div>
<div>
<ul>
<li>ZEN code has many traits in common with Zen-buddhism - serene, minimal</li>
<li>The expansion very precisely describes the programming pattern.</li>
<li>In both these ways and the fact it's pronounceable and spellable, it beats out YAGNI.</li>
</ul>
<div>
<br /></div>
<b>EVA</b> - <a href="http://www.essenceandartifact.com/2011/03/essence-and-artifact-design-principle.html">Essence Vs Artifact</a></div>
<div>
<ul>
<li>Pronounceable, short, phonetic, though not a real word</li>
<li>Clear expansion</li>
<li>I find it fun and pleasant. Maybe I've seen WALLE too many times. I always hear his voice when I see the word.</li>
</ul>
<div>
<br /></div>
<b>POET</b> - <a href="http://www.essenceandartifact.com/2013/12/principle-of-exposure-and-transparency.html">Principle of Exposure and Transparency</a></div>
<div>
<ul>
<li>Real word. One might say good poetry is both clear and has depth. This concept is mostly about clarity, but the concept itself has a lot of depth. I know that's a little forced, but every synergy between the real-word and the concept gives the acronym lift.</li>
<li>I forced 1 letter - the 'of' is included, but the 'and' is not.</li>
<li>Including the word 'principle' could be considered another form of forcing. All these acronyms are in some form 'principles' - why is this one so special it needs to be included explicitly? Nothing. It just works!</li>
</ul>
<div>
<br /></div>
<b>NINO</b> - <a href="http://www.essenceandartifact.com/2016/07/nino-beyond-wysiwyg.html">Natural-In, Natural-Out</a></div>
<div>
<ul>
<li>Pronounceable, short, phonetic</li>
<li>Expansion suggests a question - what is 'natural'? This is key to the concept - get thinking about how to make our UIs as natural as possible for humans. There is no definitive answer what that means.</li>
<li>Oh so much better than WYSIWYG as an acronym. </li>
<li>The NINO concept is bigger - a superset of WYSIWYG.</li>
</ul>
<div>
<br /></div>
<b>WLC</b> - <a href="http://www.essenceandartifact.com/2016/06/write-less-code.html">Write Less Code</a></div>
<div>
<ul>
<li>NOT pronounceable or phonetic - I hesitate using the acronym at all. However...</li>
<li>The expansion is awesome. It's super catchy and a hugely important concept. I use it all the time in my presentations. </li>
<li>WLC just becomes a shorthand. I -never- attempt to pronounce the acronym. ('wulk'? - ick)</li>
</ul>
<div>
<br /></div>
<b>SOUP</b> - <span style="font-family: "helvetica neue"; font-size: 14px;"><a href="http://www.essenceandartifact.com/2017/01/soup-showing-our-undies-vs-conscious.html">Showing Our Undies Programming</a></span></div>
<div>
<ul>
<li>expansion is funny</li>
<li>real-word</li>
<li>real-soup is not a good thing when mixed with computers, and it isn't when mixed with code</li>
<li>The SOUP concept is a form of <a href="https://en.wikipedia.org/wiki/Leaky_abstraction" target="_blank">leaky-abstractions</a> - and real soup can leak :). If you've used up 'your undies are showing' jokes, you might say to a coworker 'your SOUP is leaking.' It's a nice synergy.</li>
</ul>
<div>
<br /></div>
</div>
<h3>
Go!</h3>
<div>
Go MUYOA (Make Up Your Own Acronyms)! If you've got a concept you are revisiting regularly, try figuring out a way to capture it in a word. Who knows, it could catch on and the world could see <b><span style="color: blue;">blue</span></b> for the first time!</div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com9tag:blogger.com,1999:blog-2533554759458923621.post-32563714689919826692017-01-25T08:37:00.001-08:002017-06-01T21:32:13.371-07:00SOUP - Showing-Our-Undies vs Conscious-ProgrammingHave you ever thought, while using an application, that it should be doing this work for you? A great example is reload buttons, in particular the pull-down-to-reload UI on many mobile apps. Why should the user need to tell the app when to update its data? The app should know and automatically update its data the instant it changes.<br />
<br />
The problem is programmers getting lazy. Programming is hard. Programming problems can be hard. And sometimes... Programmers just push the problem onto the user - they ask the user to press a reload button instead of automatically updating.<br />
<br />
This mentality is ubiquitous. Apps everywhere expose the inner problems of the program that are irrelevant to the user. We programmers get lazy and <b>let our undies hang out in public</b>.<br />
<br />
<h3>
SOUP is about Quality</h3>
Laziness is not the only cause of SOUP. Real-world budget constraints and the need to get-to-market lead to cutting quality. Hard problems to solve in programming often get pushed off to the user with the conscious or unconscious justification that it's 'easy for the user to do.'<br />
<br />
Presenting the user with an <a href="http://www.essenceandartifact.com/2014/07/amazingly-great-design-howto.html" target="_blank">amazingly-well-designed</a> app is the key to success, and yet it's easy for us to forget that and let 'real-world' pressures cause us to degrade the user's experience. This destroys the magic and results in a second-rate app that is much more likely to fail.<br />
<br />
<h3>
SOUP is about Culture and Normalization</h3>
<div>
The other major problem is culture. We become normalized to a certain kind of app working a certain way. We forget to stop and ask if there is a better way for the user to accomplish their task. I think spreadsheets are in this rut. Fundamentally they haven't changed since the original Visicalc. They are great for getting started, but once you have more than a few dozen cells with calculations, they become a bear to use. </div>
<div>
<br /></div>
<div>
Programming tools are always improving. Often something that was hard in the 1970s is now easy in the 2010s. However, many UIs are still written as-if we were using the tools of the '70s, '80s or '90s.</div>
<div>
<br /></div>
<h3>
Conscious Programming</h3>
<div>
The term conscious-blah is used for many things these days: conscious-living, conscious-eating, conscious-parenting, etc. Open up google and type in 'conscious a' or any other letter of the alphabet and you'll see some similar terms show up. </div>
<div>
<br /></div>
<div>
I think all of these mean the same basic thing. We can't be conscious of everything all the time, but we can shine the light of consciousness on as many things as we can think of for a brief time each. It's about creating a practice of revising our assumptions, actions and thought processes periodically to make sure they still hold true. My life motto sums this up nicely: <b>question everything</b>. </div>
<div>
<br /></div>
<div>
I advocate for conscious-programming because there are many unfounded assumptions in programming - many <b>artifacts</b> which distract us from the <b>essence</b> of what we are trying to do. My post on <a href="http://www.essenceandartifact.com/2014/07/amazingly-great-design-howto.html" target="_blank">Amazingly Great Design</a> has some ideas on how to effectively focus on the essence of delivering value to users and cut through the jungle of artifacts.</div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com5tag:blogger.com,1999:blog-2533554759458923621.post-7123096458210360382017-01-03T12:10:00.001-08:002017-06-01T21:41:51.493-07:00Beyond CORS<h2>
The Problem with CORS</h2>
<blockquote class="tr_bq">
The App Principle: A web page is an application. In order for web pages to remain relevant in an app-driven world, web-apps must be able to do anything native apps can.</blockquote>
<br />
CORS breaks this principle. It restricts the information a web-app can fetch from the internet, and even if you are allowed to fetch it, it sometimes restricts what you can do with that information. Native Apps can fetch anything from the internet and do anything with it.<br />
<br />
CORS has other problems as well. It isn’t consistently implemented across browsers. Safari 9.x interprets HTMLImage.crossOrigin differently from other browsers. CORS setup is difficult to get right and therefor it’s easy to get it wrong and actually create exactly the vulnerabilities CORS is supposed to prevent. Last, CORS returns <a href="http://stackoverflow.com/questions/4844643/is-it-possible-to-trap-cors-errors" target="_blank">extremely opaque errors</a>.<br />
<br />
<h2>
Why Does CORS Exist?</h2>
I’ve been trying to understand this question for a year. My best understanding is, before CORS, web-apps were even more restricted. CORS opens up cross-domain access while preventing hacks such as:<br />
<br />
<ol>
<li>Badwebsite.com attempts to fetch your emails from gmail.com; if you are logged in with gmail.com, without cors, it could do this!</li>
<li>CORS “taint” - I just don’t know. Is this a way to appease copyright holders? It doesn’t really prevent anything since Native Apps aren’t restricted in this way. Further, all you have to do is set up a basic web-proxy server and your Web-App could do anything with any image on the web. I have not been able to determine any legitimate reason for the existence of 'taint.'</li>
</ol>
<br />
<h2>
CORS is the Wrong Answer</h2>
Reason #1 above is the main reason for CORS. It is legitimate from a certain perspective. There is a potential vulnerability, but it is the wrong solution. The problem is when “badwebsite.com” attempts to contact “gmail.com” it gets to freely use your cookies authenticated with gmail.com. This is something Native-Apps cannot do, so why should a web-page get to do this? And yet IT CAN - without CORS restrictions. <b>This is insane.</b> It’s like logging into the Gmail Native App on your phone , and then switching to MyMalicousApp and allowing it to send requests to Gmail using your login information from the Gmail app.<br />
<br />
<h2>
Beyond CORS - Sandboxed Cookies</h2>
It is relatively easy to solve the CORS problem now that we have separated the essence from the artifacts. We just need a way to allow websites to make external requests without giving them access to all the client’s cookies. The answer is to treat each webpage as a separate, isolated application with its own, sandboxed set of cookies for all the other webpages it communicates with.<br />
<br />
I propose we add an option to <span style="font-family: "courier new" , "courier" , monospace;">XMLHttpRequest</span> called ‘<span style="font-family: "courier new" , "courier" , monospace;">useSandboxedCookies</span>’. When true, any web-application for a given domain is now allowed to make any request to any url - just like any native app could. However, all cookies used in those requests are local to that web application. This is exactly how native-apps work.<br />
<br />
Example:<br />
<br />
<ul>
<li>Alice logs into Gmail.com directly.</li>
<li>Then she goes to MyWebsite.com, which attempts a GET from Gmail.com</li>
<li>The cookies in the GET request to gmail.com are empty - the GET originated in the sandboxed cookie-space of the MyWebsite.com app.</li>
<li>So, even though Alice is logged into Gmail.com in one tab, in the MyWebsite.com tab, requests to Gmail.com appear to be coming from a new session.</li>
</ul>
<br />
This solution doesn’t actually do anything you can’t already do with CORS. All you need to do is set up a proxy server (example: <a href="https://www.npmjs.com/package/corsproxy" target="_blank">corsproxy</a>), which returns all the right CORS headers, and any website can fetch data from anywhere on the net, taint-free. However, setting up a proxy is not generally an option because it is costly, inefficient and not library-friendly. We need a client-side solution like the one above.<br />
<br />
<ul>
<li>We should do away with the Taint concept entirely. It doesn't achieve anything useful, but it creates a lot of developer pain. Therefor, Sandboxed-cookie-requests should never return tainted objects.</li>
</ul>
<div>
<br /></div>
<h2>
Safe, Cross-Web-App Communication</h2>
My <span style="font-family: "courier new" , "courier" , monospace;">useSandboxedCookies</span> proposal above solves 99% of the CORS problem. Since it could be added to the HTML spec in addition to CORS, we could stop there. However, there is another use-case that my proposal prevents but CORS allows, however poorly.<br />
<br />
There are legitimate reasons why MyGoodWebsite might want to access Gmail.com using Alice's logged in credentials, and Gmail.com may want to allow it. For example, Gmail.com may want to offer a ‘log in with Gmail’ feature to third-party web apps. My proposal above prevents this since the only client-side code allowed to access Alice's Gmail.com cookies is Gmail.com’s code itself.<br />
<br />
We need a reliable way for two client-side apps to communicate with each other. To do this, we can add a relatively simple extension to the postMessage API: allow postMessage to post a message to a URL. When this happens, the browser fetches data from the specified URL to initialize a headless client-side javascript session. That session can then send and respond to postMessages with other client-side web apps.<br />
<br />
In the example above, MyGoodWebsite could postMessage to <span style="font-family: "courier new" , "courier" , monospace;">gmail.com/api.js</span>. Once the gmail app loads, it sends back a postMessage that it is ready. Then MyGoodWebsite can use Gmail’s custom API for authentication. The <span style="font-family: "courier new" , "courier" , monospace;">gmail.com/api.js</span> app can then use the user’s already-authenticated gmail.com cookies to communicate with the gmail.com servers and authenticate the third-party app.<br />
<br />
<h2>
Recap</h2>
<div>
I've outlined two proposals which superscede CORS and solve its problems:<br />
<br />
<ul>
<li><b>Sandboxed Cookies</b>: allow a web-app to safely fetch data from anywhere on the web with a simple client-side flag set per request, without any painful 'tainting.' Tainting is depricated.</li>
<li><b>PostMessage to URL</b>: Allow any web-app to start any other for the purpose of safe communication and safe use of authenticated cookie credentials.</li>
</ul>
<br />
I have wasted way too many hours on CORS over the past few years, and I'm sure I'm not the only one. These proposals are simple to use and implement. They would open the web up to the web itself, instead of just native apps.<br />
<br />
Does anyone know how to get the attention of the HTML5 standards committee?</div>
<div>
<br /></div>
<br />Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com3tag:blogger.com,1999:blog-2533554759458923621.post-82748790561230144842016-07-28T11:28:00.002-07:002016-07-29T00:40:24.761-07:00Simulations and Chosen Realities<div class="p1">
My best guess about the future is eventually we will all be “uploaded into the cloud.” (awkward, but it gets the meaning across)</div>
<div class="p2">
<br /></div>
<div class="p1">
It’s tempting to say we’ll all be living in a ‘simulation’ at that point. But, I think by that point we will select a new term.</div>
<div class="p2">
<br /></div>
<div class="p1">
When we say ‘simulation’ we mean something somehow inferior or an approximation to the ‘real thing.’ The problem with that notion is our perception of the ‘real world’ is always an inferior approximation of the real thing.</div>
<div class="p2">
<br /></div>
<div class="p1">
Therefor experience and perception are always a ‘simulation’ of the ‘real world.’</div>
<div class="p2">
<br /></div>
<div class="p1">
If we live in the cloud, and we experience a world that is generated for us by algorithms, as long as that experience is AT LEAST as accurate as our ‘real-world’ experiences were, then I don’t think it’s fair to call it a simulation anymore.</div>
<br />
<div class="p1">
It’s something more. It is a ‘chosen reality.’ In some sense it will be inferior since the ‘real world’ will always be more complex and nuanced than our generated ones. But the difference will be beyond our ability to perceive it. Our chosen reality will be superior <i>perceptually</i>. It will be the reality we want, not the one forced on us. </div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com2tag:blogger.com,1999:blog-2533554759458923621.post-41951708301597908492016-07-06T09:44:00.001-07:002016-07-06T09:46:21.574-07:00NINO - beyond WYSIWYGWhat-You-See-Is-What-You-Get was always an awkward acronym. Say "wizzywig" and people just look at you strangely. There is an amusing anecdote about the origin of the acronym on Wikipedia. I hope it's true:<br />
<blockquote class="tr_bq">
<span style="color: #252525; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">The phrase "what you see is what you get," from which the acronym derives, was a </span><a href="https://en.wikipedia.org/wiki/Catchphrase" style="background-attachment: initial; background-clip: initial; background-image: none; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0b0080; font-family: sans-serif; font-size: 14px; line-height: 22.4px; text-decoration: none;" title="Catchphrase">catchphrase</a><span style="color: #252525; font-family: sans-serif; font-size: 14px; line-height: 22.4px;"> popularized by </span><a href="https://en.wikipedia.org/wiki/Flip_Wilson" style="background-attachment: initial; background-clip: initial; background-image: none; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0b0080; font-family: sans-serif; font-size: 14px; line-height: 22.4px; text-decoration: none;" title="Flip Wilson">Flip Wilson</a><span style="color: #252525; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">'s drag persona </span><a href="https://en.wikipedia.org/wiki/Geraldine_Jones_(character)" style="background-attachment: initial; background-clip: initial; background-image: none; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0b0080; font-family: sans-serif; font-size: 14px; line-height: 22.4px; text-decoration: none;" title="Geraldine Jones (character)">Geraldine</a><span style="color: #252525; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">, first appearing in September 1969, then regularly in the early '70s on </span><i style="color: #252525; font-family: sans-serif; font-size: 14px; line-height: 22.4px;"><a href="https://en.wikipedia.org/wiki/The_Flip_Wilson_Show" style="background-attachment: initial; background-clip: initial; background-image: none; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0b0080; text-decoration: none;" title="The Flip Wilson Show">The Flip Wilson Show</a></i><span style="color: #252525; font-family: sans-serif; font-size: 14px; line-height: 22.4px;">. The phrase was a statement demanding acceptance of Geraldine's entire personality and appearance. <a href="https://en.wikipedia.org/wiki/WYSIWYG" target="_blank">wikipedia</a></span> </blockquote>
<h3>
</h3>
<h3>
NINO - Natural-In, Natural-Out</h3>
The 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.<br />
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
The main problem with WYSIWYG is it is only half the equation. How we put information into an app is equally important as how we get information back out. Just as we shouldn't have to perform mental gymnastics trying to anticipate how our final output will look, we shouldn't have to wade through a bewildering array of options to get our ideas into the app.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
The best interfaces are the ones that get out of the way. You know an app is well designed when you completely forget the interface and instead can dedicate 100% of your mental energy towards your creation. These interfaces tend to have two things in common.</div>
<div style="text-align: left;">
<ol>
<li>They visually get out of the way. There is less screen clutter to distract you.</li>
<li>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.</li>
</ol>
</div>
<h3 style="text-align: left;">
Comparison: Paper by FiftyThree - a NINO App</h3>
<div style="text-align: left;">
As of version 3, Paper by FiftyThree extended its excellent sketching app with note taking features. They introduce a brilliant set of natural gestures for formatting your notes that required zero screen clutter.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisBVLJLlrcX4xjCc775PJkJ_-2BkWaEl1iZB6cgtt424wqUJbemwsbzdWleXxcjvMY3OflDQfnOGyQvo4qY0x5eft9BVtwtzPkMEn8gGEhFWFCb8tmDM5jP5OvZvZV-mKih9y-AdEhzDMW/s1600/fiftythree-paper-swipe-to-style.gif" imageanchor="1"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisBVLJLlrcX4xjCc775PJkJ_-2BkWaEl1iZB6cgtt424wqUJbemwsbzdWleXxcjvMY3OflDQfnOGyQvo4qY0x5eft9BVtwtzPkMEn8gGEhFWFCb8tmDM5jP5OvZvZV-mKih9y-AdEhzDMW/s400/fiftythree-paper-swipe-to-style.gif" width="400" /></a></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMOSR1JL2IuBtiAngcD3CHb5sJPJ-PPR4TeLRJHEMxP7J6xB4bd1XcBfUIG554QX6S-trwfrDXXRxIUxkRqVJEik3vvHoyAYlZjH_MFDtJJAoWUEYsAuvEp-23xkguDM5-C6BWtFrnq0Tx/s1600/SwipeToStyle_Howto.png" imageanchor="1" style="text-align: left;"><img border="0" height="126" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMOSR1JL2IuBtiAngcD3CHb5sJPJ-PPR4TeLRJHEMxP7J6xB4bd1XcBfUIG554QX6S-trwfrDXXRxIUxkRqVJEik3vvHoyAYlZjH_MFDtJJAoWUEYsAuvEp-23xkguDM5-C6BWtFrnq0Tx/s400/SwipeToStyle_Howto.png" width="400" /></a></div>
<div style="text-align: center;">
<br /></div>
<h3 style="text-align: left;">
Comparison: Microsoft OneNote - a very Un-NINO App</h3>
<div style="text-align: left;">
By contrast, consider OneNote. It has a bewildering array of features, buttons, icons, widgets and text. My note in the screenshot below has a short title and one line of text. It is oppressively dominated by the rest of the interface.<br />
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLS7UQCyh-QZa0ocQYK6-3sPI1yUbTvAewhMT8Tt5p9Xj3P5Yk1K95a69Gv09IHUbhLp5kJS9iFlzlvmcZODuhAEypiCRyoHduYtoWSNY6fMk6oz9Io5sJgxNAs1AVOkfkdXLZ8ehOruk9/s1600/Screen+Shot+2016-07-06+at+9.53.16+AM.png" imageanchor="1"><img border="0" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLS7UQCyh-QZa0ocQYK6-3sPI1yUbTvAewhMT8Tt5p9Xj3P5Yk1K95a69Gv09IHUbhLp5kJS9iFlzlvmcZODuhAEypiCRyoHduYtoWSNY6fMk6oz9Io5sJgxNAs1AVOkfkdXLZ8ehOruk9/s640/Screen+Shot+2016-07-06+at+9.53.16+AM.png" width="640" /></a></div>
<h3 style="text-align: left;">
</h3>
<h3 style="text-align: left;">
Exocranium</h3>
<div>
Our devices, phones, tablets, computers, watches and more and more becoming extensions of our mind and body. I once heard a description of smart-phones, particularly with notes and productivity apps, as our <i>exocranium. </i>These devices and apps are becoming our brain outside our brain. The better the app, the more natural an extension of our mind and body. The better the app, the more natural its inputs and outputs - the more NINO it is.</div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com3Denver, CO 80215, USA39.747363 -105.1083542000000139.698523 -105.1890352 39.796203 -105.02767320000001tag:blogger.com,1999:blog-2533554759458923621.post-32707578018266348402016-06-12T10:26:00.000-07:002019-11-16T07:07:13.489-08:00WLC - Write Less Code<blockquote class="tr_bq">
Given two solutions to a problem, the one with less code is usually better. </blockquote>
<h4>
</h4>
<h4>
Plite of the Programmer</h4>
<br />
Our 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.<br />
<br />
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.<br />
<br />
<h4>
</h4>
<h4>
</h4>
<h4>
</h4>
<h4>
Why Count Tokens?</h4>
<br />
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.<br />
<br />
<blockquote class="tr_bq">
Don't abbreviate words. Saving keystrokes only saves writing the code. It doesn't save edits or reading. Abriviations 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.</blockquote>
<br />
Measuring tokens is a simple, effective metric that lets us make decisions quickly and get on with solving problems and delivering value.<br />
<br />
<h4>
</h4>
<h4>
</h4>
<h4>
</h4>
<h4>
Why ‘Write Less Code’?</h4>
<br />
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 <i>the</i> 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.<br />
<br />
<h4>
</h4>
<h4>
How to Write Less Code</h4>
<br />
All 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.<br />
<br />
<h4>
</h4>
<h4>
</h4>
<h4>
</h4>
<h4>
<a name="dry" href="#dry">DRY</a></h4>
<br />
Don'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.<br />
<br />
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?<br />
<br />
<h4>
</h4>
<h4>
</h4>
<h4>
</h4>
<h4>
ZEN</h4>
<br />
Build it with Zero Extra Nuts (more commonly known as YAGNI). Because it is impossible to<br />
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.<br />
<br />
It is fun to add cool features, but the master knows the only thing that matters is delivering value to the customer.<br />
<br />
<h4>
</h4>
<h4>
</h4>
<h4>
</h4>
<h4>
Write Less Code - Formalized</h4>
<div>
<br />
My hypothesis, and my experience, comes down to this:</div>
<div>
<br /></div>
<div>
<ul>
<li>Given two different functions, modules or programs</li>
<li>that both meet or exceed the problem's requirements, both correctness and performance</li>
<li><b>the one with less tokens is <i>always</i> better</b></li>
<li>as long as it doesn't sacrifice clarity.</li>
</ul>
<div>
<br /></div>
</div>
<h4>
</h4>
<h4>
The Practice of Writing Less Code</h4>
<br />
As 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.<br />
<br />Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com43Denver, CO 80215, USA39.747363 -105.1083542000000139.698523 -105.1890352 39.796203 -105.02767320000001tag:blogger.com,1999:blog-2533554759458923621.post-46804412808449279512016-02-06T10:11:00.002-08:002019-08-13T08:59:31.775-07:00ZEN Programming and Building In-House Frameworks (aka YAGNI)<blockquote class="tr_bq">
<span style="font-family: "arial" , "helvetica" , sans-serif;">ZEN - Zero Extra Nuts. ZEN code is minimalist. It is relentlessly focused on solving exactly the requirements and nothing more. </span>(3)</blockquote>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Write only what you need. It’s a profound concept. Engineers can’t help but overbuild things. For some reason this is inherent to being an engineer. In physical engineering, overbuilding is mostly an issue of up-front cost in terms of extra time and material. In software, there is also a substantial ongoing expense. The maintenance cost of code is related to its total size (1).</span></span><br />
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span>
<h3>
<span style="background-color: transparent; color: black; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">ZEN vs DRY</span></span></h3>
<br />
ZEN implicitly includes DRY (don't-repeat-yourself). Code repetition is one of the most pernicious forms of "Extra Nuts." Learn more about the subtleties of code repetition <a href="http://www.essenceandartifact.com/2016/06/write-less-code.html" style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;" target="_blank">here</a><span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;">.</span><br />
<br />
<h3>
<span style="background-color: transparent; color: black; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">ZEN and Frameworks</span></span></h3>
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;"><br /></span>
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;">Minimizing the size of the code-base is an important goal. Using standard abstractions like functions and classes can reduce the total codebase size. This isn’t the same as building a framework. </span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span></div>
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;">What is a Framework?</span></h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">A framework is a module. At their heart, modules are about encapsulation. Modules have an external interface and internal implementation. Better modules have simpler interfaces and more-isolated implementations.</span></span><br />
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;"><br /></span>
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">Frameworks are different from other modules because they are designed to be used across multiple applications. Frameworks must be the </span><span style="color: black; font-family: arial, helvetica, sans-serif; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">best possible modules</span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">. In order to work across multiple applications, a framework must have the simplest possible interface and the most isolated implementation. Frameworks should also have their own codebase and be packaged for easy reuse.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div>
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Why Do We Build Frameworks?</span></h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">If ZEN were the only value, we would never build frameworks. By the time we’ve built a solution to the required specs, we ship. End of story. That’s what ZEN tells us to do. If we only followed ZEN, our applications would include operating systems, drivers, database, compilers and every other part of our dev and runtime stack. In other words, each new application would be enormous and have a fraction of the capabilities we enjoy today.</span></span><br />
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;"><br /></span>
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">I said above that the maintenance cost of code is related</span><span style="color: black; font-family: arial, helvetica, sans-serif; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">to</span><span style="color: black; font-family: arial, helvetica, sans-serif; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">its</span><span style="color: black; font-family: arial, helvetica, sans-serif; font-style: italic; vertical-align: baseline; white-space: pre-wrap;"> total size</span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">. When we measure the size of code in an app </span><span style="color: black; font-family: arial, helvetica, sans-serif; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">we do not include frameworks</span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">. This is for good reason. The complexity a module adds to an app is proportional to its interface size and leakiness of its implementation. Frameworks are the best of modules. Their leakiness is minimal and their interface refined. A framework with millions of source-tokens may only add a few thousand tokens worth of complexity to a project using it. </span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div>
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Are In-house Frameworks Worthwhile?</span></h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Clearly using other people’s frameworks is a big win. You get 100x or more leverage in terms of complexity. You only have to maintain your application’s code base and you get all the framework’s capabilities for a very modest price. Building a framework in-house at first doesn’t seem like a good idea. The total code-size you have to maintain will increase when you take an application and factor it into an in-house framework plus the rest of the app.</span></span><br />
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;"><br /></span>
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">We talked about how application code-size is properly measured, but we haven’t talked about how that value relates to maintenance. Maintenance costs are proportional to </span><span style="color: black; font-family: arial, helvetica, sans-serif; font-style: italic; vertical-align: baseline; white-space: pre-wrap;">complexity</span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">, and complexity’s relationship to code-size is non-linear. If you double the code-size, you will more than double its complexity (2).</span><br />
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;"><br /></span>
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;">Realizing that code-complexity is non-linear in code-size reveals why it makes sense to write frameworks even if they only have one app using them. If the application’s code-size is N-tokens before we factor out the framework, and let's assume that we can cut the application code in half by factoring out the framework. There is always some overhead in writing a framework due to interface and abstraction code. We’ll assume that overhead is 10%. </span><br />
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;"><br /></span>
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">After the split, both the framework and app will have (1.1 * N/2) tokens, or (1.1 * N) total. For simplicity, our final assumption is a complexity-to-size factor of O(N</span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: super; white-space: pre-wrap;">2</span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">):</span></div>
<b style="font-weight: normal;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></b>
<br />
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Complexity before split: N</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">2</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Complexity after split: 0.6 * N</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">2</span></span></div>
</li>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">App: (1.1 * N/2)</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">2</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Framework: (1.1 * N/2)</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">2</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Total: 2 * (1.1 / 2)</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">2 </span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> * N</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">2</span></span></div>
</li>
</ul>
</ul>
<b style="font-weight: normal;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">That’s a 40% savings!</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> Granted, I made the favorable assumptions, but clearly it is possible to have large savings. Further, you don’t have to limit yourself to making just one framework. There are diminishing returns, but in my experience I've still found improvements with over 10 in-house frameworks. </span></span><br />
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;"><br /></span>
<span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">Once you have a good framework, it is possible to re-use it in other apps. Then the savings really start to compound. If we assume just two apps, using the example above, </span><span style="color: black; font-family: arial, helvetica, sans-serif; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">the complexity savings increase to 55%</span><span style="color: black; font-family: arial, helvetica, sans-serif; vertical-align: baseline; white-space: pre-wrap;">. You also get code-size savings as well - about 18%.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br /></span></span></div>
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;">When to use 3rd Party Frameworks</span></h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Obviously you should use an existing framework, if one exists, instead of writing your own. Right? Well, when evaluating the merits of a 3rd-party framework, there are a lot of things to consider. </span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Let's start with technical aspects:</span></span></div>
<b style="font-weight: normal;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></b>
<br />
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Does it do what you need it to do?</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Does it meet your performance goals?</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Is the source open?</span></span></div>
</li>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">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.</span></span></div>
</li>
</ul>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Is it OpenSource?</span></span></div>
</li>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Can you contribute improvements back to the project?</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">How clear are the maintainers about what sort of contributions are acceptable?</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">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.</span></span></div>
</li>
</ul>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">How difficult will it be to switch frameworks later? </span></span></div>
</li>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="line-height: 22.08px;">How much of your code will directly interact with the framework?</span></span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">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.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">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.</span></span></div>
</li>
</ul>
</ul>
<b style="font-weight: normal;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">There are also important non-technical aspects to evaluate:</span></span></div>
<b style="font-weight: normal;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></b>
<br />
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">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.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">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.</span></span></div>
</li>
</ul>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="white-space: pre-wrap;"><br /></span></span></div>
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;">When to Write an In-House Framework</span></h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">There are two main questions to ask each time you consider building a framework:</span></span></div>
<b style="font-weight: normal;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></b>
<br />
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Is it the</span><span style="background-color: transparent; color: black; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> best of modules</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">?</span></span></div>
</li>
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Is the interface simple?</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Will the implementation be well isolated and minimally leaky?</span></span></div>
</li>
</ul>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">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.</span></span></div>
</li>
</ul>
<b style="font-weight: normal;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></b>
<br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;">If you haven’t written a line of code yet, should you even consider writing a framework yet? You should never write something unless you know for certain you will use it. Don’t build more than you immediately need for current requirements. In this, you should always follow ZEN. </span></span><br />
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;"><br /></span>
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;">However, when looking at current requirements, it is reasonable to ask how you are going to meet them. As you do, you will be considering how to modularize your implementation. If you are doing an agile approach, this design work will happen in code as you go. If not, you may be doing some up-front design. Either way, there will be a point where you have modules. </span><br />
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;"><br /></span>
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;">As soon as you start to form modules, you should start thinking about if the modules make sense as a frameworks. If the answer is “yes” to both questions above, then package up the module immediately, put it in its own code-base, and declare it a framework. The sooner you do it, the sooner you can reap the simplification rewards. Once you do, keep following ZEN. Continue to only add functionality as you need it.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span></div>
<h4>
<span style="font-family: "arial" , "helvetica" , sans-serif;"></span></h4>
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Frameworks Clarify Thinking</span></h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: arial, helvetica, sans-serif;"><br /></span>
<span style="font-family: arial, helvetica, sans-serif;">Frameworks 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. </span><br />
<span style="font-family: arial, helvetica, sans-serif;"><br /></span>
<span style="font-family: arial, helvetica, sans-serif;">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.</span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Writing Frameworks is Hard - and Worthwhile</span></h3>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-weight: normal; line-height: 22.08px; white-space: pre-wrap;"><span style="line-height: 22.08px;"><br /></span></span></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-weight: normal; line-height: 22.08px; white-space: pre-wrap;"><span style="line-height: 22.08px;">I don't want to make this seem easy. Writing the best of all possible modules is </span><span style="line-height: 22.08px;"><i>hard</i></span><span style="line-height: 22.08px;"><i>!</i> However, it is a learnable skill. You are only going to learn a skill be practicing it - a lot.</span></span></span><br />
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;"><br /></span>
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;">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.</span><br />
<span style="font-family: arial, helvetica, sans-serif; white-space: pre-wrap;"><br /></span>
<h4>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Footnotes</span></h4>
<ol style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: decimal; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">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.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: decimal; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">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 N</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">2</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"> possible interactions. In practice the relationship between code-size and code-complexity is somewhere between O(N</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">k>1</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">) < CodeComplexity(N) < O(N</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: super; white-space: pre-wrap;">2</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">). </span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><br class="kix-line-break" /></span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">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.</span></span></div>
</li>
<li dir="ltr" style="background-color: transparent; list-style-type: decimal; vertical-align: baseline;"><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;"><span style="white-space: pre-wrap;">ZEN is roughly the same concept as YAGNI, but unlike the latter, both the word 'zen' and the expansion, 'zero extra nuts' 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.</span></span></li>
</ol>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com185tag:blogger.com,1999:blog-2533554759458923621.post-5008164796198707042014-07-05T11:45:00.000-07:002016-04-19T15:03:34.633-07:00Amazingly Great Design Howto<h2>
Video or Blog</h2>
<div>
Originally, I created this content for a presentation. I then recorded a video, now on YouTube. This post is the third incarnation, the long-form blog. Please read on, or watch the 18 minute video if that's more to your liking.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="https://i1.ytimg.com/vi/e38_C6T2PpY/0.jpg" height="266" width="320"><param name="movie" value="https://www.youtube.com/v/e38_C6T2PpY?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="https://www.youtube.com/v/e38_C6T2PpY?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<div>
<br /></div>
<h2>
Design Defined</h2>
<blockquote>
de·sign (verb) \di-ˈzīn\<br />
to plan something in your mind</blockquote>
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.<br />
<br />
<h2 id="5-examples-of-amazingly-great-design">
Five Examples</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuQpPsHRJ4aQNlbNl69GRNGsfshyI7aD7FksiVwRofTrYET3FCiDxhqHYO0NYUOosU5B1oPI8pyL_-awzDF4FnpJlSIyrqeml2Svn5XrECItJ6eErBeKoVBymglkPtk5LV_9ExTR3IdX8s/s1600/AGD10_ikea.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuQpPsHRJ4aQNlbNl69GRNGsfshyI7aD7FksiVwRofTrYET3FCiDxhqHYO0NYUOosU5B1oPI8pyL_-awzDF4FnpJlSIyrqeml2Svn5XrECItJ6eErBeKoVBymglkPtk5LV_9ExTR3IdX8s/s1600/AGD10_ikea.png" width="200" /></a></div>
<h4>
<a href="http://www.ikea.com/au/en/catalog/products/60244142/">ps vållö</a></h4>
All a watering can needs is a handle, a reservoir and a spout. Ikea manages to surprise and delight with this seemingly simple product. The proof is in the details. <br />
<em><br /></em>
<em>more with less</em> — 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.<br />
<em><br /></em>
<em>emotional</em> — Beyond function, it is beautiful. The lines are graceful. The shape is alluring. It makes you want to pick it up and feel it. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEZNMW4_YjHfjTq7fAYk0lo52tA0SOF8Y-fqM-1tMDgFWhohCBh24jtIlg-JT53UTOBMgChVPtqO4xUQ1C44gX6OucEIO9JsL3GudEWyf1ylJTyMfuIDyyzuz2agmXiUukZolv0Jc4OZxw/s1600/AGD11_wwf.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEZNMW4_YjHfjTq7fAYk0lo52tA0SOF8Y-fqM-1tMDgFWhohCBh24jtIlg-JT53UTOBMgChVPtqO4xUQ1C44gX6OucEIO9JsL3GudEWyf1ylJTyMfuIDyyzuz2agmXiUukZolv0Jc4OZxw/s1600/AGD11_wwf.png" width="200" /></a></div>
<h4>
<a href="https://itunes.apple.com/us/app/wwf-together/id581920331?mt=8">together</a></h4>
The goal of the Together iPad app from the World Wildlife Foundation is to increase awareness of endangered species and accept donations. The minimal requirements are a list of animals, their current status, and link to a donations webpage. Instead, they developed a deeply emotional experience.<br />
<em><br /></em>
<em>compelling first impression</em> — 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.<br />
<em><br /></em>
<em>beautiful, pervasive </em><i>aesthetic</i> — 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.<br />
<em><br /></em>
<em>strategic</em> — 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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMyvER6naov9uOF8QnTYR3kHfks4_ayDbo8AAfcd_6yIyYfvoLsD5efoc3g87P95Z43QRci7usyOBzqyQJRJqc8u_yZSw9EQSTvKix4ZOMnkipPFgtcge9eQdQYI7be_OkVWFemBf_JON9/s1600/AGD12_jawbone.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMyvER6naov9uOF8QnTYR3kHfks4_ayDbo8AAfcd_6yIyYfvoLsD5efoc3g87P95Z43QRci7usyOBzqyQJRJqc8u_yZSw9EQSTvKix4ZOMnkipPFgtcge9eQdQYI7be_OkVWFemBf_JON9/s1600/AGD12_jawbone.png" width="200" /></a></div>
<h4>
<a href="https://jawbone.com/speakers/jambox">jambox</a></h4>
<em>invisible engineering</em> — The Jawbone JAMBOX is an engineering triumph. It packs
an amazing amount of sound in a tiny package, but it
doesn't stop there. The packaging hides the speakers,
and the box shape communicates a promise of
simplicity. It is designed to run totally wireless.
It has excellent battery life and uses bluetooth for
audio. It's built-in microphone allows it to be used
as a speakerphone. Though it targets wire-free use,
the inclusion of a 3.5mm jack supports older devices
and gives you an alternative when bluetooth doesn't
work perfectly.<br />
<em><br /></em>
<i>holistic</i><em> excellence</em> — 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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0sa4vNI9eS6sURLRi7BuIpAgImwLiu-mTZ96OhcyCbLzqGKNsViSu9d08BeQ7QG6mZxujYNArT_rvYQD-ib75eCusCf1VfR-xFuB6YsIbgt9JTAFxDLGGWZ59zdvSVRxLHkb-JllHXY0W/s1600/AGD13_balanced.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0sa4vNI9eS6sURLRi7BuIpAgImwLiu-mTZ96OhcyCbLzqGKNsViSu9d08BeQ7QG6mZxujYNArT_rvYQD-ib75eCusCf1VfR-xFuB6YsIbgt9JTAFxDLGGWZ59zdvSVRxLHkb-JllHXY0W/s1600/AGD13_balanced.png" width="200" /></a></div>
<h4>
<a href="http://balancedapp.com/">balanced</a></h4>
<em>streamlined</em> — The Balanced iPhone app by Jaidev Soin helps you track your daily goals with minimum distractions. Balance says completing your
goals can be hard, your goal tracking app shouldn't be. Setup is accelerated by providing a catalog of common tasks reducing the number of taps required by over 90%. Logging when you complete a task is a single swipe gesture. Minimizing the most common and critical path makes the app effortless to use.<br />
<em><br /></em>
<em>differentiated</em> — 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.<br />
<br />
<h3 id="nest">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZBmFcQgRWLSIKr1xd8w6cHk8ZcS2Bt74vuhf2pJtaKc_piBnLrcXUjb8gNAkRq7iC2F0u3MgbrNGLXUmOpDHoZOTXyDBZzB1zCvlDB0Q1zDPMokUtsHczJQntTMMdxpX0W_WWnKfJ1tS9/s1600/AGD14_nest.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZBmFcQgRWLSIKr1xd8w6cHk8ZcS2Bt74vuhf2pJtaKc_piBnLrcXUjb8gNAkRq7iC2F0u3MgbrNGLXUmOpDHoZOTXyDBZzB1zCvlDB0Q1zDPMokUtsHczJQntTMMdxpX0W_WWnKfJ1tS9/s1600/AGD14_nest.png" width="200" /></a></div>
</h3>
<h4>
<a href="https://nest.com/thermostat">nest</a></h4>
<em>simple</em> — The last example is the Nest thermostat. Targeting an
industry that has been stagnant for decades, they reduced the number of controls to one
dial. Even more amazing, the dial only does one
thing: it sets the desired temperature. The display
is minimal including only the current temperature,
the desired temperature, a visual of their delta
aligned with the dial and an estimate for how long
the temperature change will take. <br />
<em><br /></em>
<em>empathic</em> — 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.<br />
<br />
Extreme focus takes what used to be a heinously
painful task of programming your thermostat and
transforms it into an effortless and joyful interaction.<br />
<br />
<h2>
Amazingly Great Design Defined</h2>
<blockquote>
a·maz·ing·ly great de·sign (noun) \əˈmeɪzɪŋl'ē grāt di-ˈzīn\<br />
Design that exceeds expectations down to the last detail.</blockquote>
<br />
<h2 id="trinity-of-amazingly-great-design">
Three Pillars of Amazingly Great Design</h2>
Focus, 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.<br />
<div>
<br />
<ul>
</ul>
<h2 id="focus">
First Pillar: Focus</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzXry3U6P8seZGYYwd_LABg7idE1Qt3eExDRkSn2dSPWUR-3aSHMjybDfhZ7rrxC9e3NHiSEPXOIab22bORuQkLY1A4tQ9G_QGwZyMW1Qp4cHKhrfS9o_C-fFS3yG9XkdnnXIXMtShcmt6/s1600/AGD_focus02_jobs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzXry3U6P8seZGYYwd_LABg7idE1Qt3eExDRkSn2dSPWUR-3aSHMjybDfhZ7rrxC9e3NHiSEPXOIab22bORuQkLY1A4tQ9G_QGwZyMW1Qp4cHKhrfS9o_C-fFS3yG9XkdnnXIXMtShcmt6/s1600/AGD_focus02_jobs.png" width="400" /></a> </div>
<div style="text-align: center;">
<i>"Focus is about saying no." - Steve Jobs</i></div>
<br />
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.<br />
<br />
<h4>
customer archetype</h4>
The 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.<br />
<br />
<h4>
use-story archetype</h4>
When 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.<br />
<br />
<h4>
singular focus</h4>
This 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.<br />
<br />
<h4>
time = features * quality</h4>
In 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.<br />
<br />
<h2 id="details">
Second Pillar: Details</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi42AIAM-tl6ONX2gaBWYEkvo7FVGnWAAZ5wP-iKWIm7tH2xHnEyYg0fmVnUIDHVp_DhibkxRbaR05Z8yjfWX30XsVytHq5Waei9_yroV9yKfo5tWMvE1g3vMHltXfm5UVLy21g_Dv7UwUW/s1600/AGD_details_02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi42AIAM-tl6ONX2gaBWYEkvo7FVGnWAAZ5wP-iKWIm7tH2xHnEyYg0fmVnUIDHVp_DhibkxRbaR05Z8yjfWX30XsVytHq5Waei9_yroV9yKfo5tWMvE1g3vMHltXfm5UVLy21g_Dv7UwUW/s1600/AGD_details_02.png" width="400" /></a></div>
<div style="text-align: center;">
<i>"The details are not the details. They make the design." - Charles Eemes</i></div>
<br />
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.<br />
<br />
<h4>
environment</h4>
<ul>
<li>Where is the
product used?</li>
<li>Is it loud or quiet, bright or dark?</li>
<li>Who is around?</li>
<li>What time of day will it be used?</li>
</ul>
<br />
<h4>
product</h4>
Assuming the product is some sort of application or
website:<br />
<ul>
<li>Are all elements aligned exactly?</li>
<li>Is there adequate white-space to make the viewer
comfortable?</li>
<li>What colors are used and are they used consistently?</li>
<li>Is the app perceived to be performant and immediately
responsive?</li>
<li>Do the animations reduce distractions or are they
themselves distracting?</li>
<li>Are the fonts legible? Do they invoke the right
emotional response?</li>
<li>How are errors handled?</li>
</ul>
<br />
<h4>
customer archetype</h4>
<ul>
<li>What is their day like?</li>
<li>Who are the important figures in their life?</li>
<li>What social groups do they belong to?</li>
<li>What are their hopes and desires?</li>
<li>What will the person be thinking just before they use
the product? Just after? </li>
<li>Will they be thinking about
the product while not using it?</li>
<li>What do we want them to feel when they use the
product?</li>
<li>How will our customer want to be perceived while
using our product publicly?</li>
</ul>
<br />
<h4>
lifecycle</h4>
<ul>
<li>How will the customer learn about the product?</li>
<li>Where will they first see it?</li>
<li>Where will they first "touch" it?</li>
<li>When is their first real engagement?</li>
<li>What is their daily engagement?</li>
<li>What is their last engagement?</li>
<li>How does the product reoccur in their thoughts after
their last engagement?</li>
<li>What details will help to reengage the user with this or other products?</li>
</ul>
<br />
<ul>
</ul>
<h2 id="tools">
Third Pillar: Tools</h2>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVbUXaFRrom_4HWkjopDFBi71uXjhx737VwB2Dr1zE61M8zNwGC6Qmk8ogmEx80_qoRZGT-h5UFWQxPJ027tTY5GdrKeTiHGaAYEy-bLfn8gAFToJK_VByyZBwKvCYVXqm82wr8BQFjmPm/s1600/AGD_ideas_03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVbUXaFRrom_4HWkjopDFBi71uXjhx737VwB2Dr1zE61M8zNwGC6Qmk8ogmEx80_qoRZGT-h5UFWQxPJ027tTY5GdrKeTiHGaAYEy-bLfn8gAFToJK_VByyZBwKvCYVXqm82wr8BQFjmPm/s1600/AGD_ideas_03.png" width="400" /></a></div>
<blockquote>
<i>"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
Jarmusch</i></blockquote>
The 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.<br />
<br />
<h4>
notebook</h4>
Keep 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.<br />
<br />
<h4>
opinion</h4>
Develop 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. <br />
<br />
<h4>
play</h4>
Constantly experiment with your tools. Free yourself
of the constraints of your real projects and allow
yourself to explore freely to discover great new
possibilities.<br />
<br />
<h4>
inspiration</h4>
Creativity 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.<br />
<br />
<h2 id="designers-amnesia">
Designer's Amnesia</h2>
In 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.<br />
<br />
Keep the following questions in mind:<br />
<ul>
<li>Is your focus the right one?</li>
<li>Are there failures in details you can no longer see because you've memorized them?</li>
<li>Is there a tool that obviously solves a problem better but you can no longer see it?</li>
</ul>
Explaining what you are working on to someone new is
a good way to expose these shortcomings. It is even
better to give them a prototype and watch them use
it. Video the session and study it in detail for every little success and failure. Often you'll be slapping your forehead in minutes.<br />
<br />
<h2 id="impact-of-amazingly-great-design">
Impact of Amazingly Great Design</h2>
Many 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.<br />
<br />
<h4>
business</h4>
<em>perceived value</em> — 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.<br />
<em><br /></em>
<em>brand</em> — 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. <br />
<em><br /></em>
<em>actual value</em> — 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.<br />
<br />
<h4>
customer</h4>
<em>time</em> — 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.<br />
<em><br /></em>
<em>reduced stress</em> - 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.<br />
<em><br /></em>
<em>beauty and delight</em> - 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.<br />
<br />
<h2 id="zen-of-amazingly-great-design">
Zen of Amazingly Great Design</h2>
Each 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.<br />
<em><br /></em>
<em>focus</em> — 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.<br />
<em><br /></em>
<em>details</em> — 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.<br />
<em><br /></em>
<em>tools</em> — 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.<br />
<br />
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.<br />
<br />
<h2>
Further Reading</h2>
<ul>
<li><a href="http://www.amazon.com/Steve-Jobs-Walter-Isaacson/dp/1451648537">Steve Jobs - Walter Isaacson</a></li>
<li><a href="http://www.amazon.com/Design-Like-Apple-Principles-Experiences/dp/1118290313">Design Like Apple - John Edson</a></li>
<li><a href="http://www.amazon.com/Design-Everyday-Things-Donald-Norman/dp/0465067107">The Design of Everyday Things - Donald A. Norman</a></li>
</ul>
</div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com4tag:blogger.com,1999:blog-2533554759458923621.post-51418888871585154132013-12-15T16:45:00.000-08:002013-12-15T16:45:30.526-08:00Principle of Exposure and Transparency - POET<h1>The Visibility Problem</h1>
<p>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.</p>
<p>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.</p>
<h1>Two Challenges of Programming</h1>
<p>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.</p>
<p>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.</p>
<p>Simulating programs in our head is a major part of modern programming. <strong>This is broken.</strong> 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.</p>
<h1>The Principle of Exposure and Transparency (POET)</h1>
<blockquote><p>POET: All bugs are trivial once their cause is exposed; given enough runtime transparency, all bugs are trivial.</p></blockquote>
<p>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.</p>
<h1>Linus's Law</h1>
<blockquote><p>Given enough eyeballs, all bugs are shallow. - Eric Raymond, <a href="http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/">The Cathedral and the Bazaar</a></p></blockquote>
<p>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.</p>
<h1>Homework</h1>
<ol>
<li>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.</li>
<li>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? ( <a href="http://sparkinspector.com/">Spark Inspector</a> was just that tool for us in a recent debug jam session for our iPad app. )</li>
</ol>Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com2tag:blogger.com,1999:blog-2533554759458923621.post-82489322385922914592013-10-09T10:51:00.001-07:002013-10-09T11:10:03.328-07:00Bugs and MutationsIt took me hours to find this bug, and it turned out to be pretty surprising. I had good check-ins before and after the change. I was refactoring my code to make the rectangle class immutable. After the change text was no longer positioned correctly: <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjymgwid2h2JKONtM1wMv8QuVD_x7LUhRnP4_wPjk8BleBQdelcCVD11s1Lj2fOJum0LI4jBD_fnHYEvrVURAqLPl04eMS-L2Nim4dtarArkbCKVGvJS_ghsJqi7hv_ip7MQYhcyg5JkjkO/s1600/Screen+Shot+2013-10-09+at+10.56.14+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjymgwid2h2JKONtM1wMv8QuVD_x7LUhRnP4_wPjk8BleBQdelcCVD11s1Lj2fOJum0LI4jBD_fnHYEvrVURAqLPl04eMS-L2Nim4dtarArkbCKVGvJS_ghsJqi7hv_ip7MQYhcyg5JkjkO/s400/Screen+Shot+2013-10-09+at+10.56.14+AM.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">correct position
</span></div>
<br><br>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBAKOYBPVeKjnW1YCfcecxK8R_IZdutt3gWK0D3bvX5_xf7fuusB70rJFqXzvAzzcGNRB_1Ga6HjdZ0D4w0p__jIK4AIuRFGFI0qyvi7JVO7ChzSj-Vn4CW8vaIhJrghedeaPPRqM_Rk4i/s1600/Screen+Shot+2013-10-09+at+10.59.26+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBAKOYBPVeKjnW1YCfcecxK8R_IZdutt3gWK0D3bvX5_xf7fuusB70rJFqXzvAzzcGNRB_1Ga6HjdZ0D4w0p__jIK4AIuRFGFI0qyvi7JVO7ChzSj-Vn4CW8vaIhJrghedeaPPRqM_Rk4i/s400/Screen+Shot+2013-10-09+at+10.59.26+AM.png" /></a></div>
<div style="text-align: center;">
<span style="font-size: x-small;">incorrect position
</span></div>
<br />
I changed one line in my text-layout code to be compatible with immutable rectangles:
<br />
<pre class="brush:ruby;">- metrics.area.location = metrics.area.location.neg.add offset
+ metrics.area = rect metrics.area.location.neg.add(offset), metrics.area.size
</pre>
I can tell you there were no bugs in the new immutable Rectangle class.
<br />
<br />
Can you spot the bug?
<br />
<br />
<br />
<hr />
<br />
<br />
There is no bug. The new line is correct, and yet that's all I changed.
<br>
<br>
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.
<br />
<br />
Here's what was actually wrong, in 3 code snippets (CoffeeScript):
<br />
<br />
1) The original code that worked but had an accidental mutation:
<br />
<pre class="brush:ruby;"> updateTextLayout: ->
offset = point()
@area = @metricsList[0].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.size
</pre>
2) Code with one line changed that seemed correct but didn't work:
<br />
<pre class="brush:ruby;"> updateTextLayout: ->
offset = point()
@area = @metricsList[0].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.size
</pre>
3) Final working code:
<br />
<pre class="brush:ruby;"> 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
</pre>Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com2tag:blogger.com,1999:blog-2533554759458923621.post-64622363957878748382013-09-11T16:57:00.000-07:002013-09-12T08:59:57.450-07:00Sashimi Coding<div class="separator" style="clear: both; text-align: center;">
<a href="http://upload.wikimedia.org/wikipedia/commons/8/89/Fugu_sashimi.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="239" src="http://upload.wikimedia.org/wikipedia/commons/8/89/Fugu_sashimi.jpg" width="320" /></a></div>
<div class="p1">
<br /></div>
<blockquote class="tr_bq">
<div class="p1">
Sashimi is a Japanese delicacy consisting of very fresh raw meat or fish sliced into thin pieces. - <a href="http://en.wikipedia.org/wiki/Sashimi">Wikipedia</a></div>
</blockquote>
<div class="p1">
Sashimi-coding* is the art of slicing up code into the smallest possible parts. Sashimi-coding works best when used consistently across the entire application. It may seem painful at first, but once you get used to it, you'll wonder how you ever lived without it.<br />
<br />
<h2>
Sashimi-Functions are Tiny</h2>
Sashimi-functions are the <i>smallest possible functions</i>.</div>
<div class="p1">
<br />
<ul>
<li><b>10 lines max</b> for dynamic languages (Javascript, Coffeescript, Ruby, Python)</li>
<li><b>20 lines max</b> for static languages (Java, C++, Objective-C)</li>
</ul>
<br /></div>
<h2>
The Five Benefits of Sashimi-Functions</h2>
<div class="p1">
</div>
<ol>
<li>Easier to understand</li>
<li>Easier to test</li>
<li>More reusable</li>
<li>Self documenting</li>
<li>Inheritance & monkey-patching friendly</li>
</ol>
<br />
<h2>
Easier to Understand</h2>
<div>
A function which is twice as long is more than twice as hard to understand. Sashimi-functions are not just a little easier to understand, they are typically much easier to understand.</div>
<div>
<br /></div>
<h2>
Easier to Test</h2>
<div class="p1">
Breaking a large function into sashimi-functions allows you to test simpler components in isolation before testing them together.</div>
<div class="p1">
<br /></div>
<h2>
More Reusable</h2>
<div>
Slicing a function into many sashimi-functions opens up the possibility of reusing sub-parts of the original function.</div>
<div>
<br /></div>
<h2>
Self Documenting</h2>
<div class="p1">
Comments in the middle of functions are a <a href="http://en.wikipedia.org/wiki/Code_smell">code-smell</a>. Sashimi-functions eliminate the need for these comments. Split the function in two, and the comment becomes the name of the new function.</div>
<div class="p1">
<br /></div>
<h2>
Inheritance & Monkey-Patching</h2>
<div class="p1">
In both cases, adding custom code must be done in whole-function units. Sashimi-functions make it easy to augment or replace only the code you care about.</div>
<div class="p1">
<br /></div>
<h2>
Performance Cost?</h2>
<div>
There is one down-side. There may be a performance cost to sashimi-functions. In static languages the compiler can usually inline away any overhead, but in dynamic languages it depends a lot on how smart the runtime environment is. </div>
<div>
<br /></div>
<div>
In almost all cases the large increase in developer productivity wins over the small decrease in performance. As always, avoid premature optimization and profile-first so you only optimize what needs optimizing.<br />
<br />
* I heard the term Sashimi Coding first from Jason Thane who in turn heard it from Nathan McCoy.</div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com6tag:blogger.com,1999:blog-2533554759458923621.post-73638204098314156862013-06-11T15:35:00.004-07:002013-06-11T15:35:52.844-07:00Riak and Monotable<div class="p1">
The Imikimi <a href="http://monotable.org/">Monotable</a> project has been placed on indefinite hold. Unfortunately we don't have the manpower. It is an excellent solution to our back-end data-store needs, and probably for many others as well. However, it is still going to require a lot of work to bring to production-ready.</div>
<div class="p2">
<br /></div>
<div class="p1">
Instead, we are looking seriously at Riak for our back-end store. We hope to put all our Kimi-data and most of our Sql-data in two separate Riak clusters. Riak has several benefits that Monotable was designed to solve:</div>
<div class="p1">
</div>
<ol>
<li>no central server - every node is the same and any node can respond to any request</li>
<li>scales easily by adding one node at a time </li>
<li>can configure replication levels on a per-bucket basis</li>
<li>supports map-reduce</li>
<li>can store binary data - up to 16 megabytes per record (this our requirement, not Riak's exact max size)</li>
</ol>
<br />
<div class="p1">
However, Riak has some down-sides:</div>
<div class="p1">
</div>
<ol>
<li>Riak's "eventually consistent" system only makes progress on a record's consistency when it is read. It is not clear that any progress is made if the record is never read after a write or consistency failure. This means the latest version of a record could go under-replicated indefinitely.</li>
<li>Riak's scaling is limited by your initial "ring-size". My hazy understanding is we need to set our ring-size to 20x our max expected server-count.</li>
<li>Riak has a lot of cross-talk between nodes. There is potentially an upper limit of 300 servers before performance degrades.</li>
<li>Riak does not allow range-selects on the primary key</li>
<li>The behavior and scalability of secondary indexes is not clear to me. Typically distributed hash tables can't do secondary indexes. Riak has secondary indexes, but there is probably a catch that we don't understand yet.</li>
<li>I don't think Riak has "live" map-reduce. </li>
</ol>
<div class="p1">
Monotable is designed to achieve all of the above goals and scale to very large sizes. However, we are a long ways from needing >300 servers. As long as Riak's indexes work reasonably well and we can do off-line map-reduce jobs without disrupting site performance, it should be good enough for us for now.</div>
<div class="p1">
<br /></div>
<h3>
Monotable and Map-Reduce</h3>
<div class="p1">
Live map-reduce was not an original requirement for Monotable. However, it is a very powerful feature. It would bring Monotable from being a simple key-value store with basic range-selects to a system with powerful indexing and querying capabilities. It turns out the core of Monotable is well suited for it.</div>
<div class="p2">
<br /></div>
<div class="p1">
In an offline map-reduce, each chunk can be stream-processed by the mapper and fed into the reducer. Once a chunk has been reduced to a single output, the results of all chunks can be merged until a single overall result is output. If the reducer can write data back to Monotable, you can use this to generate secondary indexes. </div>
<div class="p1">
<br /></div>
<div class="p1">
These indexes are more powerful than SQL indexes which have a 1-to-1 mapping between source and index records. With the reduce step we can arbitrarily choose to index at any level of reduction. In fact we can store the result of every reduction if we wish. This allows us to generate an index + aggregate hybrid. With this data structure we can compute the map-reduce result over any sub-range in O(ln n) time.</div>
<div class="p2">
<br /></div>
<div class="p1">
This much was already a possibility within the original Monotable requirements. Just take the Monotable core and add a standard map-reduce system over top. The question becomes how can we make it live-updating?</div>
<div class="p1">
<br /></div>
<div class="p1">
Acknowledgment: Live-Map-Reduce is not new. I believe CouchDB does this already. CouchDB, however, doesn't scale easily to large distributed clusters. </div>
<div class="p1">
<br /></div>
<h3>
Live-Updating Map-Reduce in Monotable</h3>
<div class="p1">
Anytime a source-record is changed, the off-line generated index will become out-of-date. Using normal map-reduce, we'd have to delete all the old data and re-run the map-reduce. Deleting a large range of records is fast in Monotable, but re-running the map-reduce will be slow. Since we are already storing the entire reduce-tree, couldn't we re-map the changed record and then update only the O(ln n) reduce steps which depend on it?</div>
<div class="p1">
<br /></div>
<h4>
Structure Definitions</h4>
<div class="p1">
First, I need to briefly describe the structure of Monotable. The entire Monotable stores all records, sorted by key. Monotable is logically partitioned into "ranges" which are similar to separate "tables" in other stores. Each range is broken up into one or more 64 meg "chunks". Each chunk exclusively covers a sub-range of the overall Monotable. All records in Monotable with keys >= the chunk's start key and < it's end key are stored in that chunk.</div>
<div class="p2">
<br /></div>
<div class="p1">
To keep things simple, let's separate out map-reduce. Each range in Monotable can have zero or more mappers or reducers. A mapper takes each record and transforms it and then writes the results back into Monotable in a different range. Each reducer takes all records in one chunk and reduces them down to one record which is written, again, to a different range. In both cases, the new range can in turn have a mapper or reducer. </div>
<div class="p1">
<br /></div>
<div class="p1">
To configure a standard map reduce, we would apply a mapper to our data-range which write records to another range we'll call the "index". The index-range would have a reducer which write records to a meta-index-range. This meta-index-range would in turn have the same reducer step to yet another meta-meta-index-range. This continues until the meta-meta-meta-*-index-range fits within one chunk.</div>
<h4>
<br class="Apple-interchange-newline" />Live Updating</h4>
<div class="p1">
Now that we have a sense of our data-structure, how do we keep it up to date? Due to the nature of distributed data, we can't afford to do it synchronously. Monotable guarantees atomic operations within a chunk, but provides no guarantees across chunk boundaries. </div>
<div class="p1">
<br /></div>
<div class="p1">
When a record changes, the first step is to mark it's chunk as "dirty" with respect to all mappers and reducers applied to that chunk. Asynchronously, the master server for each chunk can later initiate the process of "cleaning" the chunk by updating all effected maps and reductions.</div>
<div class="p2">
<br /></div>
<div class="p1">
Unfortunately, simply re-applying the map or reduce step for the chunk doesn't work. The mapper may generate arbitrary output based on the record's data. If we naively insert the new value in the index we may be forgetting to remove the old value, which may be anywhere else in the index. We must have both the old and the new value so we can delete the old value before inserting the new one. Note that if the mapped old and mapped new values are identical, we can skip the rest of the update. </div>
<div class="p1">
<br /></div>
<div class="p1">
Keeping the old value of a record adds complexities, particularly since we want to allow more than one active mapper or reducer. For every mapper/reducer we need to be able to access the version of every changed records as they were the last time that mapper/reducer ran. </div>
<div class="p1">
<br /></div>
<h4>
A New Chunk Data Structure with Versioning</h4>
<div class="p1">
I believe the answer is similar to how <a href="https://github.com/couchbaselabs/couchstore/wiki/Format">CouchDB</a> stores its entire database - as a continually appending log representation of a b-tree. This format keeps a complete revision history of all changes. Each mapper or reducer just needs to track the offset of the snapshot when it was last run. </div>
<div class="p2">
<br /></div>
<div class="p1">
If we limit this to each individual chunk, then we avoid the main problem of CouchDB: it is painful to compact large databases. Since chunks are limited in size, we always have relatively small files which will be fast to compact. We have to be a bit careful when we compact chunks to ensure that we don't lose any of the snapshots that the map/reducers need. However, if they are kept up-to-date at roughly the same rate as our compaction schedule they should usually be fairly up-to-date and we only need to keep the most recent few snapshots. We just need a compaction algorithm that takes into account a list of snapshots that must be maintained after compaction.</div>
<div class="p2">
<br /></div>
<div class="p1">
Keep in mind that all this snapshotting and revision tracking is managed within one server. No synchronization needs to happen with other servers in the cluster. </div>
<div class="p2">
<br /></div>
<div class="p1">
As a side-effect, Monotable gains a general snapshotting system. On a chunk-by-chunk bases we could establish any arbitrary history tracking plan up to tracking all history.</div>
<div class="p1">
<br /></div>
<h3>
Chaining</h3>
<div class="p1">
Now we know how on map/reduce step will stay up to date. The rest of the system falls out automatically. The mapper will dump its outputs into a separate range of Monotable which in turn will become "dirty" and trigger a reducer step. The reducer will write to yet another range triggering another reducer step. This will continue until the source range is reduced down to <= 1 chunk.</div>
<div class="p2">
<br /></div>
<div class="p1">
Chaining will add some latency to the system. Each step invokes an asynchronous delay between being marked "dirty" and the master-server for that chunk scheduling the map/reducer action. The good news is we are effectively working with a tree with very high branching factor. Pessimistically, given the minimum chunk size of 32megabytes and a large, 1k record size, we have a branching factor over 32,000. A two-level tree can address 1 billion records. Four levels can track 1 quadrillion records.</div>
<div class="p2">
<br /></div>
<div class="p1">
My other concern is how much work this might involves if there are random changes happening all over the source range all the time. Due to the asynchronous nature of the system, though, the answer is good. In the worse case, at the leaf level, there may be as many as one map operation per record change. This could be bad, but the mapper algorithm could be designed to run in time proportional to the number of changes. One change will only require a small amount of work to update.</div>
<div class="p1">
<br /></div>
<div class="p1">
As we chain "dirty" updates up the reduction tree, the story gets better. If several leaf nodes of one parent change at the same time, they will all mark their parent node as "dirty", but they won't each trigger a new reducer step. When the parent node's server schedulers the mapper step it will integrate all changes from its leaf nodes in one pass.</div>
<div class="p1">
<br /></div>
<h3>
Brilliant!</h3>
<br />
<div class="p1">
The result is quite elegant. Each individual record change would trigger approximately 'k' steps of work reading/writing only approximately 'k' records - where 'k' is the depth of the reduction tree <= log(n) / log(32000) - n == number of records in the source range. K is <= 2 for n <= 1,000,000,000 records, and K is <= 4 for n <= 1,000,000,000,000,000,000 records. If records are changing faster than the reduction steps can propagate up the tree, k will become smaller since updates up the tree can cover more than one child-node per update. K will approach 1 as the speed of record updates increases. The system gets <i>more</i> efficient as it becomes more loaded.</div>
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com3tag:blogger.com,1999:blog-2533554759458923621.post-50500259292537480442013-01-31T16:48:00.000-08:002013-09-11T18:52:31.733-07:00Parsing JSON the Not-So-Hard Way With Ruby and Babel BridgeAaron Patterson recently posted this article on <a href="https://practicingruby.com/articles/shared/scqtutaqfldp">Parsing JSON the hard way</a> using <a href="http://rubygems.org/gems/racc">Racc</a>. I think he did an excellent job explaining Racc. However, it was painful. Racc is an LALR(1) parser-generator similar to Yacc. While Yacc was fun to learn in school, it's also painful to use. LALR is hard to debug ("shift-reduce conflict" - !@#$% - if you know what I mean), and the parser generation steps are tedious to set up and maintain. There is a better way...
<br />
<br />
Enter <a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar">Parsing Expression Grammars</a>. I learned about PEGs from <a href="http://treetop.rubyforge.org/">Treetop</a>. Think of PEGs as greedy regular expressions with recursion. Being greedy, they don't try every possible pattern-match. This turns out to be a good thing; it makes them much easier to understand and debug. Adding recursive rule-matching to regular expressions makes PEGs approximately as expressive as LALR(1) parsers (though not identical). Treetop got me excited to work with parsers again, but sadly it still had some of the awkwardness of Yacc-style parser-generators. You have to build "treetop" files into ruby files before you can use them. There is yet an even better way...
<br />
<br />
Enter <a href="http://babel-bridge.rubyforge.org/">Babel Bridge</a> (<a href="https://github.com/shanebdavis/Babel-Bridge">github</a>). I wanted a PEG based parser-generator that allowed me to use 100% ruby with no extra build steps, so I built Babel Bridge. I've been evolving BB for over 2 years now. It is a powerful tool for building easy-to-understand parsers.
<br />
<br />
Here is how to write a JSON parser using the Babel Bridge gem. If you want to skip to the punch-line, here is the <a href="https://github.com/shanebdavis/Babel-Bridge/tree/master/examples/json">JSON parser source code</a>.
<br />
<br />
<h1>
Writing a JSON parser with Babel Bridge</h1>
First, install the babel_bridge gem:
<br />
<pre class="brush:bash;">gem install babel_bridge
</pre>
With Babel Bridge you can create many different parsers and have many instances of each in one runtime. To define a new parser, create a class and inherit from BabelBridge::Parser.
<br />
<pre class="brush:ruby;">
require "babel_bridge"
class JsonParser < BabelBridge::Parser
# define the parser here
end
</pre>
The main component for defining your parser is the "rule". A rule is a named pattern for matching strings of characters. The first parameter of the "rule" method is the name of the rule. The remaining parameters specify one or more patterns to match. For more detailed info, please see the <a href="https://github.com/shanebdavis/Babel-Bridge">readme</a>.
<br />
<br />
There are five literal values that are allowed with JSON: string, number, true, false and null. Let's start by making rules for each of them. (Credit: I used Aaron Patterson's regular expressions he derived from <a href="http://json.org/">json.org</a>.)<br />
<pre class="brush:ruby;">
require "babel_bridge"
class JsonParser < BabelBridge::Parser
rule :value, any(:number, :string, :true, :false, :null)
rule :string, /"(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*"/
rule :number, /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/
rule :true, "true"
rule :false, "false"
rule :null, "null"
end
BabelBridge::Shell.new(JsonParser.new).start
</pre>
In addition to the five rules for the literals, I added two more lines of code. First, I added a general rule called :value. It matches any of the five literals. Babel-Bridge starts matching using the first rule you declare. That "root rule" must include everything you want to match. JsonParser will now match any of the JSON literals. Second, I added a "shell". It is a Babel-Bridge tool to help make parser-testing easier. Try running the above code and typing in some JSON literals at the prompts.
<br />
<br />
<pre class="brush:ruby;">
> "string literal"
Parse tree:
ValueNode1 > StringNode1 > "\"string literal\""
> 123
Parse tree:
ValueNode1 > NumberNode1 > "123"
> null
Parse tree:
ValueNode1 > NullNode1 > "null"
</pre>
We are halfway done. There are two more important patterns for JSON: objects (hashes) and arrays. Arrays consist of 0 or more :values, delimited by "," and wrapped in "[]". Objects consist of 0 or more :pairs, again delimited by "," and wrapped in "{}". Pairs consist of a :string, then a ":", then a :value.
<br />
<pre class="brush:ruby;">
require "babel_bridge"
class JsonParser < BabelBridge::Parser
rule :value, any(
:object, :array, :number,
:string, :true, :false, :null
)
rule :array, '[', many?(:value, ','), ']'
rule :object, '{', many?(:pair, ','), '}'
rule :pair, :string, ':', :value
rule :string, /"(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*"/
rule :number, /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/
rule :true, "true"
rule :false, "false"
rule :null, "null"
end
BabelBridge::Shell.new(JsonParser.new).start
</pre>
You can try out the new rules:
<br />
<pre class="brush:ruby;">
> ["my string",123,true]
Parse tree:
ValueNode1 > ArrayNode1
"["
ValueNode1 > StringNode1 > "\"my string\""
ValueNode1 > NumberNode1 > "123"
ValueNode1 > TrueNode1 > "true"
"]"
> {"my key":"my value"}
Parse tree:
ValueNode1 > ObjectNode1
"{"
PairNode1
StringNode1 > "\"my key\""
":"
ValueNode1 > StringNode1 > "\"my value\""
"}"
</pre>
If JSON allowed literals to stand alone, we'd be done. Unfortunately JSON is a little more restrictive, so we have to add a new root-rule to ensure there is an array or object at the top-most level.
<br />
<br />
There is one other thing we need to add. Parsing-Expression-Grammars match every character or fail. Right now we are not handling white-space, so any white-space character in our string will cause our parsing to fail. BB makes this easy. Just call "ignore_whitespace" in your class declaration.
<br />
<br />
Below is the complete JSON parser. It should match any legal JSON and reject anything illegal. However, it just returns the parse-tree when it succeeds. In the next section we'll add the same functionality Aaron did in his blog post.
<br />
<pre class="brush:ruby;">
require "babel_bridge"
class JsonParser < BabelBridge::Parser
ignore_whitespace
rule :document, any(:object, :array)
rule :array, '[', many?(:value, ','), ']'
rule :object, '{', many?(:pair, ','), '}'
rule :pair, :string, ':', :value
rule :value, any(
:object, :array, :number,
:string, :true, :false, :null
)
rule :string, /"(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*"/
rule :number, /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/
rule :true, "true"
rule :false, "false"
rule :null, "null"
end
BabelBridge::Shell.new(JsonParser.new).start
</pre>
<a href="https://github.com/shanebdavis/Babel-Bridge/blob/master/examples/json/json_parser.rb">source</a>
<br />
<h1>
Adding Functionality to The Parse Tree</h1>
Every rule you define creates a node class. Every time an instance of that rule is parsed, an instance of that node class is created. With Babel-Bridge you can easily define methods on the parse-tree nodes for each rule you declare. When calling the rule method, just open up a do-block. The code inside the do-block is executed inside the class for that node.
<br />
<br />
Our goal now is to convert the resulting parse-tree from our JSON parser into the equivalent Ruby Hashes, Arrays and Strings etc. We are going to add an "evaluate" method to our nodes which returns the correct Ruby data-structures. For example, here is how we can add the evaluate method to our :null rule.
<br />
<pre class="brush:ruby;">
rule :null, "null" do
def evaluate; nil end
end
</pre>
To evaluate the remaining JSON literals we can leverage the fact that Ruby's literals are nearly identical. In fact, "null" is the only one which is different. To avoid duplicating code (DRY!), I'm going to insert an extra rule called :ruby_compatible_literal. Calling to_s on a node just returns the source string that node matched. Using Ruby's "eval" method, we can evaluate that string and get the Ruby object back.
<br />
<pre class="brush:ruby;">
require "babel_bridge"
class JsonParser < BabelBridge::Parser
ignore_whitespace
rule :document, any(:object, :array)
rule :array, '[', many?(:value, ','), ']'
rule :object, '{', many?(:pair, ','), '}'
rule :pair, :string, ':', :value
rule :value, any(:object, :array,
:ruby_compatible_literal, :null
)
rule :ruby_compatible_literal, any(:number,
:string, :true, :false
) do
def evaluate; eval(to_s); end
end
rule :string, /"(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*"/
rule :number, /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/
rule :true, "true"
rule :false, "false"
rule :null, "null" do
def evaluate; nil end
end
end
BabelBridge::Shell.new(JsonParser.new).start
</pre>
Next, let's add the evaluate method to array. When there are nested rules, you can access them by name. If that sub-rule can be matched more than once, it will return an array of the child nodes which were matched with that rule. Here, the #value method returns a :value nodes in matched in the array. We just need to convert that array to the #evaluated versions of each :value node.
<br />
<pre class="brush:ruby;">
rule :array, '[', many?(:value, ','), ']' do
def evaluate; value.collect {|v| v.evaluate}; end
end
</pre>
Evaluating Objects takes two steps. The :pair rule returns a 2-element array of the form: [key, value]. Then the :object rule uses the Hash[] constructor for the final result.
<br />
<pre class="brush:ruby;">
rule :object, '{', many?(:pair, ','), '}' do
def evaluate; Hash[ pair.collect {|p| p.evaluate } ] end
end
rule :pair, :string, ':', :value do
def evaluate; [ eval(string.to_s), value.evaluate ] end
end
</pre>
Here is the full source-code for parsing JSON and generating Ruby data structures.
<br />
<pre class="brush:ruby;">
require "babel_bridge"
class JsonParser < BabelBridge::Parser
ignore_whitespace
rule :document, any(:object, :array)
rule :array, '[', many?(:value, ','), ']' do
def evaluate; value.collect {|v| v.evaluate} end
end
rule :object, '{', many?(:pair, ','), '}' do
def evaluate; Hash[ pair.collect {|p| p.evaluate } ] end
end
rule :pair, :string, ':', :value do
def evaluate; [ eval(string.to_s), value.evaluate ] end
end
rule :value, any(:object, :array, :ruby_compatible_literal, :null)
rule :ruby_compatible_literal, any(:number, :string, :true, :false) do
def evaluate; eval(to_s); end
end
rule :string, /"(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*"/
rule :number, /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/
rule :true, "true"
rule :false, "false"
rule :null, "null" do
def evaluate; nil end
end
end
BabelBridge::Shell.new(JsonParser.new).start
</pre>
<a href="https://github.com/shanebdavis/Babel-Bridge/blob/master/examples/json/json_parser2.rb">source</a>
You'll notice that we didn't have to define evaluate on every node. Babel-Bridge has some intelligent defaults to help minimize code-size. Now run the code and enter some JSON values:
<br />
<pre class="brush:ruby;">
> [null]
=> [nil]
> {"my key":"my value"}
=> {"my key"=>"my value"}
</pre>
Notice that the shell stopped printing our parse-tree. The shell looks for the "evaluate" method on the root node. If it exists, it prints out root_node.evaluate.inspect.
You might also try inputing some illegal values. This shows off one of Babel-Bridge's powerful debugging tools - the parser-failure-info.
<br />
<pre class="brush:ruby;">
> [nil]
Parsing error at line 1 column 2 offset 1
Source:
...
[<HERE>nil]
...
Parse path at failure:
DocumentNode1
Expecting one of:
"[" ArrayNode1
"]" ArrayNode1
"false" FalseNode1
"null" NullNode1
"true" TrueNode1
"{" ObjectNode1
/"(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*"/ StringNode1
/-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/ NumberNode1
</pre>
If you want to use your parser in real code, you probably won't want to use the shell. Here's how:
<br />
<pre class="brush:ruby;">
json_parser = JsonParser.new
parse_tree = json_parser.parse "[null]"
if parse_tree
ruby_data_structure = parse_tree.evaluate
puts ruby_data_structure.inspect
else
puts "ParsingError: " + json_parser.parser_failure_info
end
</pre>
For further reading, you might be interested in my earlier blog post: <a href="http://www.essenceandartifact.com/2012/09/how-to-create-turing-complete.html">How to Create a Turing Complete Programming Language in 40 Minutes</a> (and 70 lines of code).<br />
<br />Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com5tag:blogger.com,1999:blog-2533554759458923621.post-2614434911101508982013-01-12T12:28:00.002-08:002013-01-13T08:35:27.530-08:00Don't Learn a New Programming Language Every Year. Write one!<h1><em>Don't</em> learn a new language every year</h1>
<p>Programmers often recommend learning a new programming language every year. I don't agree. I've studied many languages by reading their specs and dabbling with some code until I feel like I've got the basics, but I don't think I really learned them. My path to really "learning" Ruby showed me why.
<p>Ruby was not a challenging language to learn. I picked up the Pragmatic Programmers book and read it end to end (an endorsement to both the language and the book). When the time came to start Imikimi, I chose Rails to do the web-side. However, I discovered that I hadn't really learned to *think* in the language until after several years of continuous professional use.
<p>I was a C++ programmer before I was a Ruby programmer. A lot of my early Ruby code looks and feels a lot like C++ code. There were constructs in Ruby that I wasn't comfortable with, so I simply didn't use them. Over time I re-discovered language features I "learned" in my first reading of the Pragmatic book. Over time I learned how to program in Ruby-style from the community. By studying the Rails source and other gems I learned how to better use the language and how to write clean, readable code.
<p>Learning a language by reading a book and writing a few small sample apps is equivalent to learning the grammar and a few phrases of spoken language. It's a shallow understanding which only broadens your perspective in shallow ways. I don't think you can claim to really know a language, spoken or programming, until you are conversant in it. It's a long, slow, but ultimately rewarding processes.
<p>Here's my recommendation: To get started, do learn a few extra languages, shallowly. The second and third language you learn will broaden your horizons even if you don't dive too deep into them. After that, though, you need to focus on deepening your understanding either of your current language of choice, or a new one, through hours and hours of work on real projects, OR through my second recommendation:
<h1>Write a Toy language every few years</h1>
<p>I'm writing a programming language. I've spent more than a decade thinking about programming languages and PL design. From 2001 until 2006 I worked on new language ideas full-time. Unfortunately none of that work saw the light of day, so I'm circling around again. I've learned a lot since then, primarily from Ruby and the Ruby community.
<p>My current project, the River programming language, is an attempt to build the simplest Prototype-Based core language that can support a Ruby-like class-system on-top, written in the language itself. I've learned more about Ruby in the past few months than I have in the past few years.
<p>You learn a lot about programming when you write a language implementation. It forces you to examine all the edge cases you normally ignore. And it happens fast. You are immediately forced into uncomfortable areas of programming languages you were unaware of. There are trade-offs to be made at every level. There are boot-strapping issues to resolve, and there are a host of subtle semantics in your host language that you never thought about.
<h1>How to get started</h1>
If you decide to follow this path, here are a few tips.
<ul>
<li>Use a flexible, agile host language. You will make many major refactors along the way, and you don't want to get bogged down in irrelevant details. This is true for any project, but especially true when working on something as meta as writing one language inside another. I'd recommend Ruby, but Python or even Javascript would work well.
<li>Use a well-designed parser-generator (resource: my <a href="http://babel-bridge.rubyforge.org/">Babel-Bridge</a> parser-generator gem)
<li>Don't worry about performance at first, even if that is your primary goal.
<li>Target Turing-complete functionality before all else. This will give you a solid base-camp to build out from as you explore the rest of your language. (resource: my <a href="https://www.youtube.com/watch?v=_Uoyufkb5lk">How to write a Turing-Complete Programming Language in 40 minutes</a> video)
</ul>
<p>You can follow my design progress on Twitter: <a href="https://twitter.com/search?q=%23riverlang&src=hash">#riverlang</a> / <a href="https://twitter.com/shanebdavis">@shanebdavis</a>
<p>Happy PL design!
Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com3tag:blogger.com,1999:blog-2533554759458923621.post-26203000895588881272012-12-04T09:58:00.001-08:002012-12-05T14:41:05.236-08:00Essence of MVC<p>The Model-View-Controller pattern (MVC) was first <a href="http://heim.ifi.uio.no/~trygver/1979/mvc-1/1979-05-MVC.pdf">described</a> at Xerox PARC by Trygve Reenskaug in 1979:</p>
<blockquote><p>MVC was conceived as a general solution to the problem of users controlling a large and complex data set. The hardest part was to hit upon good names for the different architectural components. Model-View-Editor was the first set. After long discussions, particularly with Adele Goldberg, we ended with the terms Model-View-Controller.</p>
<p><cite><a href="http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html">Trygve Reenskaug</a></cite></p></blockquote>
<p>Since then it has become the central pattern of virtually every application framework from the desktop to the web to mobile. I learned MVC from frameworks such as Rails and Cocoa, but my understanding lacked clarity. I wanted to reach beyond these artifacts and understand the essence of MVC, so I went in search of answers. After considerably more effort than I expected, I think I found some. This page is my current, best understanding of what MVC is and why it matters.</p>
<h2>What is MVC?</h2>
<p>Let's start with a simple, visual definition.</p>
<h4>MVC is a pattern for taking a program...</h4>
<div class="separator" style="clear: both; text-align: center;">
<a alt="Monolithic Program before MVC Modularization" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD6bSAQ2kwWEwm6a-cNTOdRLaWinWQ5xZ6mpkSH1FwiDB4bakA4_FVBwVC4VcNqZMyev_gU7YHAK4w5Vd71h-EdbmOmvVhwmzdxh0jaTqgZPHpgcX-qpOy_VjorvGKCfLR39SBgFBgijZR/s1600/mvc_decoupling_1.PNG" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="186" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD6bSAQ2kwWEwm6a-cNTOdRLaWinWQ5xZ6mpkSH1FwiDB4bakA4_FVBwVC4VcNqZMyev_gU7YHAK4w5Vd71h-EdbmOmvVhwmzdxh0jaTqgZPHpgcX-qpOy_VjorvGKCfLR39SBgFBgijZR/s400/mvc_decoupling_1.PNG" /></a></div>
<h4>and pulling it apart...</h4>
<div class="separator" style="clear: both; text-align: center;">
<a alt="Separating out MVC roles" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq_93XlFSpdgGHAkTETreFNd40J7xftQUn0ikf55zB3l_rRgOlamuYhJEs2XKcLyWjoCrhum5FGoFRIHPIkbR-xtbN_jdesFzKz8OUmzhxYF1w01E2MLTI4f3msEyt3hnjgeD297FbzmIm/s1600/mvc_decoupling_2.PNG" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="148" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhq_93XlFSpdgGHAkTETreFNd40J7xftQUn0ikf55zB3l_rRgOlamuYhJEs2XKcLyWjoCrhum5FGoFRIHPIkbR-xtbN_jdesFzKz8OUmzhxYF1w01E2MLTI4f3msEyt3hnjgeD297FbzmIm/s400/mvc_decoupling_2.PNG" /></a></div>
<h4>into modules with three well-defined roles:</h4>
<div class="separator" style="clear: both; text-align: center;">
<a alt="Crystalized Model-View-Controller (MVC) Roles" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhizJJ1ycY9DSGDGMzCZQ5QiXPRT54702FrN2LfqOCz3Ki2KKRUOv3ktaWfRY5fXMgUOe4hcrB-CcSjaGYADn6Hwg4c6-qfz3NdnEQFDWJLjSJuauCWV9bft5qSPWtK2qYLqPHUT22xusiR/s1600/mvc_decoupling_3.PNG" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="162" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhizJJ1ycY9DSGDGMzCZQ5QiXPRT54702FrN2LfqOCz3Ki2KKRUOv3ktaWfRY5fXMgUOe4hcrB-CcSjaGYADn6Hwg4c6-qfz3NdnEQFDWJLjSJuauCWV9bft5qSPWtK2qYLqPHUT22xusiR/s400/mvc_decoupling_3.PNG" /></a></div>
<p>The structure of a well organized MVC system is usually fairly simple. In general, there can be any number of model, view and controller modules. The communication channels between modules are restricted by an important rule: connections are only allowed between controllers and other modules. Non-controller modules should never talk directly to each other. Though not a rule, one more restriction is typically observed. Usually each view has only one controller associated with it.</p>
<div class="separator" style="clear: both; text-align: center;">
<a alt="Model-View-Controller (MVC)" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJV_rB2IruJRtdcljMSWPOgpZdpyqmNSql4LgI5jqv1-mX_dImu6LVvHuNrBBtkodkHPNn1nQnj2zEye2xbrJp9Inmwsjj9m7GUXN2HYVbQceu1k6PIBuYA4KZj9DO1C_aDYpLxmRhfsbq/s1600/mvc_decoupling_4.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="280" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJV_rB2IruJRtdcljMSWPOgpZdpyqmNSql4LgI5jqv1-mX_dImu6LVvHuNrBBtkodkHPNn1nQnj2zEye2xbrJp9Inmwsjj9m7GUXN2HYVbQceu1k6PIBuYA4KZj9DO1C_aDYpLxmRhfsbq/s400/mvc_decoupling_4.png" /></a></div>
<blockquote><p>NOTE: Advanced systems might use MVC hierarchically.</p></blockquote>
<p>Now that we have a high-level idea of the structure of a MVC program, let's look at the three roles in detail.</p>
<h3>The Model Role</h3>
<p>A model's job is to hide and protect the user's important data. This is the data the user might want to access in 10 years - the data that has real-world significance. The model role draws a line between the data the user cares about preserving and the data that is temporary or can be re-generated from the models.</p>
<p>The internals of a model are responsible for storing the actual bytes that represent the user's data. Models are also responsible for ensuring the integrity and consistency of their data. Last, a model must provide efficient methods for querying and altering its data.</p>
<p>More than any other part of the system it is important to maintain a well defined API for each model. In order for a model to do its job properly, all methods of extracting and altering its data must be well defined, understood and respected.</p>
<h3>The View Role</h3>
<p>Views are the public face of a system. They determine how a user <em>feels</em> about the system. The attributes that make a view great are as much determined by psychology and aesthetics as engineering and science. A view's primary job is to communicate data to the user as effectively as possible. Their secondary job is to communicate the interactive nature of the interface.</p>
<p>Views encompass all aesthetic concerns of their system. All presentation assets, such as images, fonts, styles and layouts, belong in a view. Code that transforms data into pixels also belongs in the views. The view may even have hooks for specifying which elements are to receive user inputs, but all input processing should be done in the controller. The focus of the view is letting the UX designer worry about how the data and interface are presented.</p>
<h3>The Controller Role</h3>
<p>A controller's job is to process user inputs and coordinate the relevant views and models. In the simple case, it starts by extracting information from a models, doing some preliminary processing and then handing the processed data to a view to be presented. When new user inputs arrive, the controller validates them, performs alterations to the model on the user's behalf and updates the view.</p>
<p>The controller role's modular boundary is not as well defined as the view or model roles. Controllers do everything models and views don't. However, they tend to have a structure which is well defined by the system's use-cases. Controllers are organized around <em>how</em> the system will be used. They provide the glue between any number of views and any number of ways to extract and alter data from the models and align them to fulfill the user's needs.</p>
<h3>MVC Roles and Relationships Diagram</h3>
<p>This diagram summarizes the MVC pattern, each of the roles and their relationships:</p>
<p><div class="separator" style="clear: both; text-align: center;">
<a alt="Model-View-Controller Roles" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhorLTcE6alicxMxif5CZkABVgeIeNJV61CX9fqfPhBVYOIRHV4vcfRzIrZ2wApQKTOkZABgZcJjkTQvzBRrdObPuVJo39ZGflNTFdsxSFYdsaS2AdVHpL7UsgioM65lzCLkil79DRVHX-i/s1600/mvc_role_diagram.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="184" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhorLTcE6alicxMxif5CZkABVgeIeNJV61CX9fqfPhBVYOIRHV4vcfRzIrZ2wApQKTOkZABgZcJjkTQvzBRrdObPuVJo39ZGflNTFdsxSFYdsaS2AdVHpL7UsgioM65lzCLkil79DRVHX-i/s400/mvc_role_diagram.png" /></a></div>
</p>
<h2>Why use MVC?</h2>
<p>With the roles of MVC defined, the next question is why do they matter. What are the benefits of MVC? How do we make use of MVC most effectively to realize those benefits?</p>
<p>There are three main benefits I have discovered.</p>
<h3>Separation of Concerns</h3>
<blockquote><p>"The central idea behind MVC is code reusability and separation of concerns."</p>
<p><cite><a href="http://www.yiiframework.com/doc/guide/1.1/en/basics.best-practices">yiiframework.com</a></cite></p></blockquote>
<p>MVC identifies <em>a very specific set of concerns</em> that are repeated in virtually every programming project:</p>
<p>MVC concerns by function:</p>
<ul>
<li><strong>Model:</strong> safely and consistently store the data that matters to the user</li>
<li><strong>View:</strong> present all, a subset or summarization of the data to the user</li>
<li><strong>Controller:</strong> respond to user inputs and events, update the view and model appropriately</li>
</ul>
<p>MVC concerns by expertise:</p>
<ul>
<li><strong>Model:</strong> data reliability, data consistency, query efficiency, update efficiency and storage-size efficiency</li>
<li><strong>View:</strong> graphic design, information presentation and UX</li>
<li><strong>Controller:</strong> expertise in the problem domain and coordinating the other concerns</li>
</ul>
<p>MVC concerns by people:</p>
<ul>
<li><strong>Model:</strong> algorithm and data-engineers</li>
<li><strong>View:</strong> designers and artists</li>
<li><strong>Controller:</strong> experts in what the system needs to do</li>
</ul>
<p>These are very different people. Sometimes we are forced to wear more than one of these hats, but ideally we would have different people responsible for each concern. MVC lets people with different expertise focus on what they do best.</p>
<h3>Managing Complexity and Mental Modes</h3>
<p>MVC is an abstraction, and like many abstractions it adds complexity. However, like good abstractions, it compartmentalizes complexity. MVC can dramatically reduce the complexity of each part of the system.</p>
<p>MVC is a special case of the general concept of modularity, and is a surprisingly good first-pass for designing a system's modularity. Why is it better than the alternatives? The core reason is the concerns MVC uses to define module boundaries are exceptionally well aligned with the real-world.</p>
<p>The MVC concerns closely parallel how we learn and think and the kind of specialists society produces. The model reflects a highly analytical mindset whereas the view requires the most creative thinking. The controller is the most political because it must balance the needs of many potentially conflicting concerns.</p>
<p>MVC is a good modularization pattern because it isolates three major modes of thinking. All the hard-analytical work of the system is isolated in models and can be done while ignoring everything else. The creative, intuitive and emotional work of a view can be done without worrying about any analytical concerns. The only sane way to make sure every user's needs get met is to ignore the <em>details</em> and instead focus on the big picture. That happens in controllers. Good MVC design not only modularizes code but it also compartmentalizes our mental modes for working on the code.</p>
<h3>Decoupling & Evolution</h3>
<p>Perhaps the most important aspect of MVC concerns the long term maintainability of code. MVC decouples the system's three main components allowing them to evolve independently.</p>
<p>In a monolithic system there are many opportunities for coupling artifacts. Changes to the visual layout, data-hiding or visual encoding are much more likely to effect data on disk. They may even break file backward compatibility. In the other direction, changes in how data is stored such as adding or removing fields, or restructuring for increased reliability, consistency or efficiency are in danger of breaking views or being exposed directly to the end user. Not only do changes anywhere in the system potentially effect all other parts of the system, but because of those large scale implications, in large projects any number of people may need to be consulted before making those changes.</p>
<p>MVC creates a strongly decoupled system. By minimizing the interface between each part and making sure each concern is handled by the right component, most changes only effect the component being changed. Decoupled views, for example, can change their presentation and even present new slices and summations of the data with no change to any models and little change to its controller.</p>
<p>Decoupling the model allows all kinds of changes to be made without touching controllers or views. It is nearly trivial to maintain backward compatibility when changing a file format: make two models, one for each version. It is much easier to add or remove information from a decoupled model. Placing all model related code inside a well defined module also makes it easy to make powerful changes to its performance. For example, it becomes much easier to add indexes for accelerating queries.</p>
<p>Sometimes it is impossible to make changes in a monolithic system that are trivial in a well modularized MVC system. Decoupling can make the impossible possible. Changes which were previously difficult can become easy, and programmer productivity typically skyrockets. The bottom line is model, view and controller modules can evolve much faster independently than they can as a monolithic whole.</p>
<h2>An Alternative Description</h2>
<p>Many great people have contributed to MVC over the past 30+ years. Apple has been a strong proponent of MVC design since 2002 with the introduction of OSX. The modern Macintosh operating system is based strongly on Objective-C which in turn is a marriage of C and SmallTalk. Since MVC was the "SmallTalk way", it's only natural for OSX to follow. Apple has a nice description of MVC:</p>
<blockquote><p>The Model-View-Controller design pattern (MVC) is quite old. Variations of it have been around at least since the early days of Smalltalk. It is a high-level pattern in that it concerns itself with the global architecture of an application and classifies objects according to the general roles they play in an application. It is also a compound pattern in that it comprises several, more elemental patterns.</p>
<p>Object-oriented programs benefit in several ways by adapting the MVC design pattern for their designs. Many objects in these programs tend to be more reusable and their interfaces tend to be better defined. The programs overall are more adaptable to changing requirements - in other words, they are more easily extensible than programs that are not based on MVC.</p>
<p><cite><a href="https://developer.apple.com/library/ios/#documentation/general/conceptual/CocoaEncyclopedia/Model-View-Controller/Model-View-Controller.html">Objective-C & Cocoa Documentation</a></p></blockquote>
<h2>The Essence of MVC</h2>
<p>The question is not <em>if</em> you should modularize your system but <em>how</em>. Model-View-Controller is an excellent first pass. If you are programming in an object-oriented language you almost certainly should be using it.</p>
<p>The gospel of MVC as I've come to understand it comes down to three carefully chosen definitions with three key benefits:</p>
<h3>Definitions of MVC</h3>
<p>MVC is a modularization pattern that classifies all modules in the system into three roles:</p>
<ul><li><strong>Model:</strong> consistently store, query and alter the important data</li>
<li><strong>View:</strong> communicate model data and user interface to human or computer clients</li>
<li><strong>Controller:</strong> receive, interpret, validate, act on and respond to client inputs or other events</li>
</ul>
<h3>Benefits of MVC</h3>
<ul>
<li>MVC allows data-engineers, UX designers and system experts to focus on what they do best.</li>
<li>MVC is an excellent way to compartmentalize complexity and isolate mental modes.</li>
<li>The model, view and controller can evolve much faster independently than they could as a monolithic whole.</li>
</ul>
<p><a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by/3.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>.
Copyright (c) Shane Brinkman-Davis, December 2012</p>Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com8tag:blogger.com,1999:blog-2533554759458923621.post-9210196380865949942012-10-18T08:04:00.000-07:002012-10-18T11:41:13.480-07:00Literate RandomizerYesterday I was seeding my database for a new Rails project. This project has profile pages with large free-form text fields. In order to get a good sense of how the site layout feels with real data, I needed some decent fake profiles. The existing tools we were using just weren't cutting it.
<p>There are several gems available to help with this task.
<p>Here is a quick-link to <a href="https://github.com/Imikimi-LLC/literate_randomizer">Literate Randomizer's readme and source</a>.
<h4>Faker</h4>
<a href="http://faker.rubyforge.org/">Faker</a> is great for generating fake names and addresses, but when it comes to generating fake prose, it follows the Loren Impsum model of obvious nonsense. This was not going to cut it:
<blockquote>
<p>Mollitia id adipisci. A voluptatum et veritatis quas enim veniam consectetur. Id perferendis quia eum et. Rerum consequatur harum quisquam impedit sit et.
<p>Qui est qui autem inventore esse laboriosam. Vitae expedita numquam eveniet repudiandae voluptatibus est in. Ratione eos maxime ut debitis illo. Voluptatibus ea molestiae et quas non est.
<p>Et ut distinctio qui nihil consequatur odio. Labore voluptas magni sapiente totam. Sed sed est nobis quia temporibus pariatur. Nihil accusamus molestiae qui occaecati ut. Sed consequatur nobis quis consequatur rerum.
</blockquote>
<h4>random_data</h4>
<a href="https://github.com/tomharris/random_data">RandomData</a> was next. RD did generate some more convincing prose, but if you glance the source you'll see it is simply randomly selecting from 23 fixed sentances
<br />
<blockquote>
<p>Soaring through all the galaxies in search of Earth flying in to the night. Every stop I make I make a new friend; Can't stay for long just turn around and I'm gone again. Hey there where ya goin, not exactly knowin'. Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum. He just keeps on movin' and ladies keep improvin'.
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. He's going everywhere, B.J. McKay and his best friend Bear. Ulysses, fighting evil and tyranny with all his power and with all of his might. Ulysses, fighting evil and tyranny with all his power and with all of his might. Every stop I make I make a new friend; Can't stay for long just turn around and I'm gone again.
</blockquote>
<h4>Literate Randomizer</h4>
If you want to generate a lot of random prose, neither of the above options work well. With a little googling I ran across <a href="http://openmonkey.com/blog/2008/10/23/using-markov-chains-to-provide-english-language-seed-data-for-your-rails-application/">this post</a> by Tim Riley. In it he shows some code for using <a href="http://en.wikipedia.org/wiki/Markov_chain">Markov-Chains</a> to generate plausible prose generated based on a source text. Using that source text, we can get a probability distribution of which words follow which words. Given that we can generate some near-english truly random sentences.
<p>Note: RandomData has a Markov tool, too, but it is very limited. I found another gem that just copy-pasted Tim's code into a gem-file, but it wasn't properly packaged nor usable.
<p>I was bummed to realize Tim hadn't made a gem of his wonderful little insight, so I thought I'd dive in and do it for him. I thought I could just copy Tim's code, give him credit, and release a nice clean gem. Turns out it wasn't that simple, or perhaps I just had too much fun with this problem. Another problem with all the tools above is they don't give you much control over the randomly generated output. I wanted control over the length and number of sentences as well as the number of paragraphs. I wanted interesting punctuation. With Markov chaining, you end up with a lot of sentences that end in prepositions (the, and, of, etc...).
<p>The result, is a nice little gem called <a href="http://rubygems.org/gems/literate_randomizer">literate_randomizer</a>. Here is a simple example. For more, please go to the <a href="https://github.com/Imikimi-LLC/literate_randomizer">literate randomizer source/readme</a>.
<pre style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtM_JPqgdRlqKqK6QBu887hIN0kQq3UHltmi9zUAPz8yRrHTwXK4sHN9XnVOmenaT8AEVZhCFIxM5q6lZy97rdnHQQr5yqZJQeAxm_P14UhxdyGaq7NBRmclkx0VyJm521k_evNPYjODbA/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"><code style="color:#000000;word-wrap:normal;"> require 'literate_randomizer'
LiterateRandomizer.word
# => "frivolous"
LiterateRandomizer.sentence
# => "Muscular arms round opening of sorts while Lord John Roxton."
puts LiterateRandomizer.paragraphs
</code></pre>
The last line outputs:
<blockquote>
<p>Memory at the narrative may have already as I could be reflected upon. Society in a dozen. Headquarters for the stream. Stream which if we. Iguanodon's hide and admirably the right line of Project Gutenberg-tm electronic. Forgive me down hull-down on every detail which! Until they were. Mantelpiece in front of a necklace and that same scene. Eighteen of a creature beside his white merchant or hope.
<p>Rain must be. Falls the paths which may have opened out we limped homewards sadly mauled and no. AGREE THAT THE CHAIRMAN. Twentieth century and horrible havoc. Train of Crayston Medal for canoes we are the scent and they. Swooped something which had a purpose than the envelope but if this. Entirely sir why this book. All these creatures that on through the rope dangled down the dinosaurs. Exhaust of the vertebrate stage of them and it began amid shouting gesticulating. Worthy of the old volcanic vents and distribute it away and under the prevailing. Assured that they took into line of the cliff. Unloosed a frugal breakfast of it run to the chasm which with. Loosened our thwarted wishes of dark until they took one's heart to win through. Cotton jacket which you can exhibit to gain a refund of hers outlined.
<p>Novelist could have a jacket which communicated with its wing. Colliery explosion and stroking. Town was justified if ever moved upon his remarks had returned to bring. XIII A Sight which the plateau and many small Japanese tray of fairyland. Sadly mauled and flitted about that all turning these lumps of such. Cutting a sentiment. Grieved for us give. Whites our largest I should be confuted if animals then the prospect of the risk? Camberwell tram with a sheet of language is our zareba.
</blockquote>
LiterateRandomizer.paragraphs options:
<ul>
<li>:first_word => nil - the first word of the paragraph
<li>:words => range or int - number of words in sentence
<li>:sentences => range or int - number of sentences/paragraph
<li>:punctuation => nil - punction to end the paragraph with<br>(nil == randomly selected from punctuation_distribution)
<li>:paragraphs => range or int - number of paragraphs
<li>:join => "\n\n" - join the paragraphs<br>If :join => false, returns an array of the paragraphs
</ul>Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com6tag:blogger.com,1999:blog-2533554759458923621.post-38951306739813361042012-09-27T14:16:00.000-07:002012-09-27T14:16:06.108-07:00Learnable ProgrammingMore great stuff from Bret Victor: <a href="http://worrydream.com/LearnableProgramming/">http://worrydream.com/LearnableProgramming/</a><br />
<br />
Start by jumping through and watching the embedded videos. They are self explanatory. Watch them right now. It'll only take a few seconds each.<br />
<br />
I started working along a similar line about a decade ago. I called it "interactive execution". The key idea is the program is re-run with every single change you make. All values are logged. You can see the actual inputs and outputs of every function for the entire run. You can see them update in realtime as you edit your code. It is easy to dismisses these ideas as non-applicable in "real-world-code":<br />
<br />
<blockquote class="tr_bq">
<div style="background-color: white; color: #555555; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 21px; margin-bottom: 12px; margin-top: 12px; padding: 0px;">
These design principles were presented in the context of systems for learning, but they apply universally. An experienced programmer may not need to know what an "if" statement means, but she does need to understand the runtime behavior of her program, and she needs to understand it while she's programming.</div>
<div style="background-color: white; color: #555555; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 21px; margin-bottom: 12px; margin-top: 12px; padding: 0px;">
A frequent question about the sort of techniques presented here is, <b style="color: black; margin: 0px; padding: 0px;">"How does this scale to real-world programming?"</b> This is a reasonable question, but it's somewhat like asking how the internal combustion engine will benefit horses. The question assumes the wrong kind of change.</div>
<div style="background-color: white; color: #555555; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 21px; margin-bottom: 12px; margin-top: 12px; padding: 0px;">
Here is a more useful attitude: <b style="color: black; margin: 0px; padding: 0px;">Programming has to work like this.</b> Programmers <i style="margin: 0px; padding: 0px;">must</i> be able to read the vocabulary, follow the flow, and see the state. Programmers <i style="margin: 0px; padding: 0px;">have to</i> create by reacting and create by abstracting. Assume that these are <i style="margin: 0px; padding: 0px;">requirements.</i> Given these requirements, how do we <i style="margin: 0px; padding: 0px;">redesign programming?</i></div>
</blockquote>
<br />
I believe it isn't that hard to imagine how to apply "interactive execution" to real-world code. Two simple tricks allow you to achieve useful application of these ideas in any sized (single-threaded) code-base:<br />
<br />
<ol>
<li>Allow the programmer to select a function as the start-point. Execute the program up to the start of that function and start a transaction against the entire running state of the code. Then, roll back the transaction with every change and restart execution from that start function.</li>
<li>Run the execution in a separate thread from the editing thread. Every character typed aborts the execution and restarts it. If the execution takes a second or two, that's OK. When the programmer wants to see the current outputs, they just stop typing for a bit. If it takes minutes or hours, the programmer is in charge of picking a better start point for her transactional, interactive-execution session.</li>
</ol>
<br />
This is really powerful stuff. I've often noticed that the skill level of a programmer is proportional to how long they can go between coding and executing their code to see if it works. The key skill here is being able to simulate the computer in your head. What a waste! The computer can simulate itself much better than your head can. Let the computer do what it's good at, and leave the human mind open to being creative.<br />
<br />
I liked this quote about OO:<br />
<br />
<blockquote class="tr_bq">
<span style="color: #555555; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 13px; font-style: italic; line-height: 21px;">Bob Barton [said] "The basic principle of recursive design is to make the parts have the same power as the whole." For the first time I thought of the whole as the entire computer, and wondered why anyone would want to divide it up into weaker things called data structures and procedures. Why not divide it up into little computers... Why not thousands of them, each simulating a useful structure?</span></blockquote>
<br />
I think I'll start calling objects "little computers".Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com2tag:blogger.com,1999:blog-2533554759458923621.post-27759337307716302012012-09-19T20:57:00.000-07:002012-09-19T21:47:11.263-07:00How to Create a Turing Complete Programming Language in 40 MinutesUsing a programming language is cool. Writing a programming language is cooler. Writing one in 40 minutes rocks! I just released a screencast on how to create a Turing Complete programming language in 40 minutes and 70 lines of code using my Babel Bridge parser generation gem and Ruby.<br />
<br />
In this example I use my Babel Bridge parser-generator gem: <a href="http://babel-bridge.rubyforge.org/">homepage</a> / <a href="https://github.com/shanebdavis/Babel-Bridge">github</a><br />
<br />
Here is the <a href="https://github.com/shanebdavis/Babel-Bridge/blob/master/examples/turing/turing.rb">70-line-source-code</a> from the screencast.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/_Uoyufkb5lk/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/_Uoyufkb5lk?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/_Uoyufkb5lk?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />
We continue to need fresh minds and new approaches to programming. There are many great challenges facing us in improving programmer productivity and supporting programming in our massively parallel age. I hope this screencast wets your appetite to pick up a parser-generator and play around with your own language. Maybe you'll invent the next Ruby, Java or Javascript!Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com6tag:blogger.com,1999:blog-2533554759458923621.post-53574197482638997552012-03-19T20:11:00.001-07:002013-12-13T12:56:01.157-08:00Bret Victor - Inventing on Principle<br />
I want to recognize excellence. Bret Victor's talk on Inventing on Principle is excellent. Go watch it now if you haven't already. <a href="http://vimeo.com/36579366">vimeo-link</a><br />
<br />
I loved how the first half exactly paralleled thoughts I've had for a long time which I've summed up as POET: the Principle of Exposure & Transparency - any problem becomes trivial with enough exposure. I was thinking more from the solving-problems angle where Bret Victor was thinking from the creativity angle. I think the ideas mirrored nicely. I definitely liked how he visualized interactive-execution in text-code. That's a nut I hadn't cracked yet. This is just the tip of the ice-berg. Lots of interesting work to be done here.<br />
<br />
The principled approach of the second half of Bret's talk was fascinating. I've had a focused path for most of my career, but even still, after watching his talk I've had a hard time simplifying my path down to a single principle. I'm not sure if that's because I don't fully understand my path's essence as well as Bret understands his or if some goals are not distillable down to a one-sentence description. I like his point regarding how a good principle can give you guidance where-as a bad one can be meaningless. "Write beautiful code" - meaningless. "Creators need immediate connection with what they are creating" - meaningful and provides a system of measuring, giving feedback and guiding you through design-space.<br />
<br />
I feel pretty strongly about eliminating "artifacts". Historical legacies that are no longer relevant can gum up the works, particularly when they are hidden in plane sight. I also love to invent. As a contrast to eliminating artifacts, I am also drawn to "essential" technologies. What technologies, if they existed, and were done "right" (with as little artifacts as possible) could change the world? I suppose in that light, my Essence & Artifact theme might just be my core principle. Eliminate artifacts; understand the Essence. One might argue it's closer to the meaningless end of the principle continuum. It certainly isn't as concrete as "No Modes". On the other hand, every feature, function, design and architecture can be measured against an Occam's Razor of "is this Essential, or is it Artificial?"<br />
<br />
Essence is timeless, simple, powerful, maximally applicable, modular, and focused. But be careful, the purely essential is also purely theoretical.<br />
<br />
Artifacts are historical, complex, constrained, difficult, narrowly focused and/or un-focused. But be respectful, artifacts are the only things that are actual.Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com1tag:blogger.com,1999:blog-2533554759458923621.post-53030803325831834712011-12-15T23:16:00.000-08:002011-12-15T23:16:09.241-08:00Where do Profits come from?This week's EconTalk Podcast: <a href="http://www.econtalk.org/archives/2011/12/munger_on_profi.html">Munger on Profits, Entrepreneurship, and Storytelling</a><br />
<br />
In this week's EconTalk Munger and Robers presented and discussed several mini-stories about trading. They explored many angles of society's common, mistaken malignment of trade. Specifically, the malignment of profit acquired solely through trade without actually "producing anything". The entire 'cast is excellent and well worth your time listening to or reading the transcript (also available at the link above).<br />
<br />
I want to point out two statements from the pod-cast that were particularly awesome.<br />
<br />
<div style="text-align: center;">
<span style="font-family: Times, 'Times New Roman', serif; font-size: large;">"The source of profits is correcting errors."</span></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
The whole quote is:</div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="color: #333333; font-family: verdana; line-height: 14px; text-align: left;">The source of profits is correcting errors. The economy around us is full of errors. And what I mean by errors is a maladjustment, a divergence between what we are actually producing and what we "should" produce in order to use the stuff that we have--our mental resources, physical capital, labor--to produce the highest possible level of satisfaction of what the public wants.</span> </span><span style="color: #333333; font-family: verdana; font-size: x-small; line-height: 14px; text-align: left;">-Munger</span><span style="font-size: x-small;"> </span></blockquote>
<br />
If you chew on that for a bit you'll find it is an astonishingly deep insight. In economics there is a concept of optimality where supply has been balanced to exactly meet demand and price has been adjusted to exactly match costs. In other words, an optimal market has no profits. What we have, instead, in the real world, is a sub-optimal market. Resources have not been balanced optimally. There are gaps in the market where goods and services are not being put to their optimal use. If someone can discover these, they can connect the good or service with a more optimal use, benefitting both the producer and the consumer, and gaining some profit. All three parties benefit from the trader <i>correcting an error in the market</i>.<br />
<br />
Now for the second awesome statement. First I'll paraphrase:<br />
<br />
<div style="text-align: center;">
<span style="font-family: Times, 'Times New Roman', serif; font-size: large;">Trading as a more equitable means of maximizing </span></div>
<div style="text-align: center;">
<span style="font-family: Times, 'Times New Roman', serif; font-size: large;">individual satisfaction than 'goodwill'.</span></div>
<br />
The second statement is from the last story Munger and Roberts discuss. It appears to be a true story about a British officer name R.A. Radford who had a background in economics and became a POW during WWII. His POW camp of 2400 inmates lived solely on rations provided by the red cross. The rations were identical for every inmate and identical month to month. From an economics point of view, the production of the entire closed society was static and egalitarian. This clearly sets up a fascinating case-study for how a society might organize when production is not an issue. Radford wrote up his economic observations later in an essay which is available online: <a href="http://www.albany.edu/~mirer/eco110/pow.html">The Economic Organisation of a P.O.W. Camp - R.A. Radford</a>.<br />
<br />
The whole quote, directly from Radford's essay is:<br />
<blockquote class="tr_bq">
<span style="font-family: Verdana, sans-serif; font-size: x-small;">Very soon after capture people realized that it was both undesirable and unnecessary, in view of the limited size and the equality of supplies, to give away or to accept gifts of cigarettes or food. "Goodwill" developed into trading as a more equitable means of maximizing individual satisfaction.</span> <span style="font-family: Verdana, sans-serif; font-size: x-small;">-Radford</span></blockquote>
<br />
What a wonderful statement! Wonderful, I suppose, if you are already pro-free-markets. If you think about it, though, it makes sense. If I give you the bits of my rations I don't want I may benefit you some, but I don't know if you are the person in camp who would benefit <i>most</i> from my gift. How should I answer that question? I need some way of finding out the value of my extra rations to every person in the camp. The problem is there are 2400 people in the camp, and they each have some bit of extra rations they too aren't using and would like to find the most valuable use for. How do you solve such a complicated problem, and do you really need the cooperative 'goodwill' of all 2400 people?<br />
<br />
No, you just need trade.<br />
<br />
Trade and, by implication, a price system are the best known way of solving such a complicated constraint optimization problem. Every single trade benefits both parties, generating wealth for both. If it were not so, they wouldn't trade. If there are inefficiencies in the trades, if the overal economy is sub-optimal, if there are <i>errors</i> in the system, then traders can arise to correct those errors and bring the overall system closer to optimality profiting themselves, yes, but also the people they trade with, and via proof-by-mathematical-induction, everyone in the camp.<br />
<br />
<i>Fascinating!</i> This simple podcast which was pretty light as EconTalk goes really got me thinking.<br />
<br />
<span style="font-size: x-small;">NOTE: All the above assumes the trades are without fraud or coercion. This appears to have been mostly true in the POW example, though if you read the essay, various interesting market failures did occur, and were, for the most part, corrected by market forces. Roberts and Munger to address this in their discussion as well.</span>Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com2tag:blogger.com,1999:blog-2533554759458923621.post-66218995573594200042011-09-22T16:20:00.000-07:002011-09-22T16:20:49.223-07:00Parsing, Ruby and Babel-Bridge<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/VctMzMjbDqo?feature=player_embedded' frameborder='0'></iframe></div>
<br />
Here is the video from a recent talk I did on parsing and the <a href="http://babel-bridge.rubyforge.org/">Babel-Bridge</a> gem I wrote for generating parsers with ease in Ruby. I recommend viewing it full-screen in 480 or 720p so you can see the text in the live-demo. Enjoy!Shane Brinkman-Davis Delamorehttp://www.blogger.com/profile/15859226113816420309noreply@blogger.com2