Fullasagoog

voisen.org

Some insight into how the Goog sees your feed. You might find it useful for trouble shooting - we certainly do.

Stomach Contents: Structure - struct
author
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
name Sean Voisen
encoding UTF-8
entry
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <blockquote><p>I’ve been diving into some heavy Mac OS X programming with Cocoa for the past few weeks, so I thought I should start sharing some of the many tips and techniques I’ve discovered along the way.</p></blockquote> <p>Many – if not most – Mac applications involve the loading and display of images. The difference in how you author such applications depends on how many images you have to load, and how frequently you have to move or display them. If all you have to do in your application is display a few static local images, then you can probably use <code>NSImageView</code> on the main thread and call it a day. This tutorial isn’t for you.</p> <p>If, however, you have to rapidly load and display hundreds or thousands of remote images on a moving canvas, <code>NSImageView</code> simply won’t cut it. Instead, you need multiple threads and the power of Core Graphics and Core Animation. These are amazing tools, but the strategies and techniques you employ in their use can mean the difference between a stuttering, unresponsive UI and the kind of smooth, fluid application experience Mac users have come to expect and love.</p> <p>Here are four simple techniques I’ve found that can help ensure your app is as performant as possible when it comes to loading and displaying images:</p> <h2>Use Core Animation Layers</h2> <p>Apple advises against large display list trees. This means that using hundreds of <code>NSImageViews</code> at once is simply a poor choice if you’re looking for any kind of performance. Instead, use <a href="https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CALayer_class/Introduction/Introduction.html"><code>CALayers</code></a>. <code>CALayers</code> are much lighter than <code>NSViews</code>, and more importantly, they are mapped to the GPU, which means that the graphics processor will do all of the heavy lifting, freeing the CPU for other things.</p> <p>Displaying an image in a <code>CALayer</code> is relatively easy. Create a layer-backed <code>NSView</code> (using <code>setWantsLayer:</code>), then add as many sublayers to your view’s layer as you like.</p> <p>In Snow Leopard, Apple added the ability to set <code>CALayer</code>’s contents property an <code>NSImage</code> instance, making it stupid simple to draw an image to a layer. <em>But beware:</em> this simple functionality comes at a cost, and is only advisable for smaller images. I’ll explain more in a bit.</p> <h2>Load in the Background</h2> <p>The main thread of your application is responsible for responding and rendering the user interface. This means that any intensive processing that happens on the main thread will make your app slow or unresponsive. When it comes to loading and displaying the images in your <code>CALayers</code>, push as much work as you can off of the main thread. This means, first and foremost, <em>do not</em> load your images on the main thread. <code>NSImage</code> and <code>NSData</code>’s loading methods are synchronous and blocking. Instead, load your images in the background. The best and easiest way to do this is to use <code>NSOperationQueue.</code></p> <p><code>NSOperationQueue</code> allows you to batch your background work into individual “operations” and then send submit them to a magical queue that will take care of prioritizing the tasks and executing them in a series of background threads. As of Snow Leopard, <code>NSOperationQueue</code> makes use of <a href="http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html">“Grand Central Dispatch (GCD),”</a> Apple’s system for multicore support in iOS and OS X, so there’s really no reason not to use it if you can.</p> <p>The code to use <code>NSOperationQueue</code> for image loading looks something like this (assuming you’re using ARC):</p> <div class="highlight"><pre><code class="objc"><span class="n">NSImage</span> <span class="o">*</span><span class="n">image</span><span class="p">;</span> <span class="n">NSOperationQueue</span> <span class="o">*</span><span class="n">loadQueue</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSOperationQueue</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span> <span class="p">[</span><span class="n">loadQueue</span> <span class="nl">setMaxConcurrentOperationCount:</span><span class="mi">2</span><span class="p">];</span> <span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">startLoad:</span><span class="p">(</span><span class="n">NSURL</span> <span class="o">*</span><span class="p">)</span><span class="nv">url</span> <span class="p">{</span> <span class="p">[</span><span class="n">loadQueue</span> <span class="nl">setSuspended:</span><span class="n">YES</span><span class="p">];</span> <span class="n">NSInvocationOperation</span> <span class="o">*</span><span class="n">operation</span><span class="p">;</span> <span class="n">operation</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSInvocationOperation</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithTarget:</span><span class="n">self</span> <span class="nl">selector:</span><span class="k">@selector</span><span class="p">(</span><span class="nl">loadImage:</span><span class="p">)</span> <span class="nl">object:</span><span class="n">url</span><span class="p">];</span> <span class="p">[</span><span class="n">itemLoadQueue</span> <span class="nl">addOperation:</span><span class="n">operation</span><span class="p">];</span> <span class="p">[</span><span class="n">itemLoadQueue</span> <span class="nl">setSuspended:</span><span class="n">NO</span><span class="p">];</span> <span class="p">}</span> <span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">loadImage:</span><span class="p">(</span><span class="n">NSURL</span> <span class="o">*</span><span class="p">)</span><span class="nv">url</span> <span class="p">{</span> <span class="n">image</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSImage</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithContentsOfURL:</span><span class="n">url</span><span class="p">];</span> <span class="p">[</span><span class="n">self</span> <span class="nl">performSelectorOnMainThread:</span><span class="k">@selector</span><span class="p">(</span><span class="n">displayImage</span><span class="p">)</span> <span class="nl">withObject:</span><span class="nb">nil</span> <span class="nl">waitUntilDone:</span><span class="n">NO</span><span class="p">];</span> <span class="p">}</span> <span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">displayImage</span> <span class="p">{</span> <span class="p">[</span><span class="n">someLayer</span> <span class="nl">setContents:</span><span class="n">image</span><span class="p">];</span> <span class="p">}</span> </code></pre> </div> <p>A few things to note here:</p> <ul> <li>None of the above handles error checking in case of corrupted or incomplete image downloads. As they say in textbooks, I’ll leave that as an exercise for the reader. Hopefully this is enough to get started.</li> <li>I’ve set the <code>maximumConcurrentOperationCount</code> on the queue to a relatively low number. Without being set, the queue will create as many concurrent operations as possible, spawning off so many threads that it often becomes a performance bottleneck if there are many items in the queue. You many want to tweak this value to your particular use case.</li> <li>Pay attention to the use of <code>performSelectorOnMainThread.</code> <strong>UI updates must happen on the main thread,</strong> and this includes setting a layer’s contents property. If you don’t, the layer will not update immediately, and will instead update at some unknown time (or not at all). Alternatively, you can use <code>[CATransaction flush]</code> after setting the contents on the background thread to achive the same effect. This will force the layer to render (on the main thread), but I find <code>performSelectorOnMainThread</code> to be both a better practice and more explicit.</li> </ul> <p>For more information on <code>NSOperationQueue</code>, see <a href="http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues">Ray Wenderlich’s extensive tutorial</a>.</p> <h2>Use Core Graphics Images Where Necessary</h2> <p>Remember when I said that setting a <code>CALayer</code>’s contents property to a large <code>NSImage</code> is unadvisable? Here’s why:</p> <p>When you set a <code>CALayer</code>’s contents property, you are replacing the layer’s the “backing store” with your image content, immediately changing the appearance of the layer. Prior to OS X 10.6, you had to set the contents of a layer to a Core Graphics image (<code>CGImageRef</code>) in order for this to work. With Snow Leopard and later, you can now set the contents to an <code>NSImage</code> instance.</p> <p>While this is a nice feature, it has a flaw: <code>CALayers</code> “live” on the GPU, while <code>NSImages</code> do not. There seems to be a performance cost as the <code>NSImage</code> is “pushed” to the GPU in order to be rendered. For small images, this cost is often unnoticeable. But for large images it becomes readily apparent.</p> <p>Because a <code>CALayer</code>’s contents have to be set on the main thread, setting them to a sufficiently large <code>NSImage</code> will cause the UI to “hiccup” as the data is pushed to the GPU. The trick instead is to do this “pushing” in the background by generating a <code>CGImageRef</code> as part of your <code>NSInvocationOperation</code> task. How do you do this? Put something like the following in your image loading method:</p> <div class="highlight"><pre><code class="objc"><span class="n">NSGraphicsContext</span> <span class="o">*</span><span class="n">context</span><span class="p">;</span> <span class="n">context</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSGraphicsContext</span> <span class="n">currentContext</span><span class="p">]</span> <span class="n">graphicsPort</span><span class="p">];</span> <span class="n">NSRect</span> <span class="n">rect</span> <span class="o">=</span> <span class="n">NSMakeRect</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">image</span><span class="p">.</span><span class="n">width</span><span class="p">,</span> <span class="n">image</span><span class="p">.</span><span class="n">height</span><span class="p">);</span> <span class="n">cgImage</span> <span class="o">=</span> <span class="p">[</span><span class="n">image</span> <span class="nl">CGImageForProposedRect:</span><span class="o">&amp;</span><span class="n">rect</span> <span class="nl">context:</span><span class="n">context</span> <span class="nl">hints:</span><span class="nb">NULL</span><span class="p">];</span> </code></pre> </div> <p>Then, in the main thread, set the contents of your <code>CALayer</code> to the <code>CGImageRef</code> instance instead of the <code>NSImage</code> instance. You will need to use a bridged-cast:</p> <div class="highlight"><pre><code class="objc"><span class="p">[</span><span class="n">layer</span> <span class="nl">setContents:</span><span class="p">(</span><span class="n">__bridge</span> <span class="kt">id</span><span class="p">)(</span><span class="n">cgImage</span><span class="p">)]</span> </code></pre> </div> <p>Note that <code>CGImageForProposedRect</code> manages the <code>CGImageRef</code> for you, so there is no need to manually free it. This means do not use <code>CFBridgingRelease</code> when setting the contents.</p> <h2>Cheat with CAAnimation’s Fill Mode</h2> <p>Even with small images, sometimes the performance penalty of using an <code>NSImage</code> for a <code>CALayer</code>’s contents is noticeable. One “hack” I’ve discovered is to use Core Animation to set the contents as part of an animation’s <code>fillMode</code>. I’m not entirely sure why this works, but it does.</p> <p>Generally speaking, using Core Animation’s <code>fillMode</code> and and <code>removedOnCompletion</code> properties to retain the effects of an animation is bad practice. It causes the presentation layer of the layer to permanently hang around, and can give unexpected results when checking a layer’s <code>frame</code> or <code>bounds</code> after animating its position or transform. Perhaps not surprisingly, this is probably why this hack works: the presentation layer’s backing store is changed instead of the layer’s actual backing store. (Experts: feel free to enlighten me.)</p> <p>So if all you are changing is a layer’s contents, this may be a worthwhile hack. Use it in the main thread:</p> <div class="highlight"><pre><code class="objc"><span class="n">CABasicAnimation</span> <span class="o">*</span><span class="n">crossFadeAnimation</span><span class="p">;</span> <span class="n">crossFadeAnimation</span> <span class="o">=</span> <span class="p">[</span><span class="n">CABasicAnimation</span> <span class="nl">animationWithKeyPath:</span><span class="s">@&quot;contents&quot;</span><span class="p">];</span> <span class="p">[</span><span class="n">crossFadeAnimation</span> <span class="nl">setDuration:</span><span class="mf">0.25</span><span class="p">];</span> <span class="p">[</span><span class="n">crossFadeAnimation</span> <span class="nl">setFromValue:</span><span class="n">self</span><span class="p">.</span><span class="n">contents</span><span class="p">];</span> <span class="p">[</span><span class="n">crossFadeAnimation</span> <span class="nl">setToValue:</span><span class="n">image</span><span class="p">];</span> <span class="p">[</span><span class="n">crossFadeAnimation</span> <span class="nl">setFillMode:</span><span class="n">kCAFillModeForwards</span><span class="p">];</span> <span class="p">[</span><span class="n">crossFadeAnimation</span> <span class="nl">setRemovedOnCompletion:</span><span class="n">NO</span><span class="p">];</span> <span class="p">[</span><span class="n">layer</span> <span class="nl">addAnimation:</span><span class="n">crossFadeAnimation</span> <span class="nl">forKey:</span><span class="s">@&quot;contents&quot;</span><span class="p">];</span> </code></pre> </div> <p>And there you have it. Just a few tips and tricks I have learned in the past few weeks. If you find any errors or misinformation, feel free to write.</p>
id http://sean.voisen.org/blog/2013/04/high-performance-image-loading-os-x
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2013/04/high-performance-image-loading-os-x
title
Stomach Contents: Structure - struct
value High-performance image loading in OS X
updated 2013-04-15T07:00:00Z
2
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>In software, prototype engineering is a necessity of innovation, but many organizations do it wrong. They do it wrong because they look at prototypes not as prototypes, but as new alpha- or beta-version products. As a result, they over-design and they over-engineer. It's worth emphasizing: <strong>prototypes are not products.</strong> The value of a prototype lies in the experience and knowledge gained through rapidly investigating a problem-space, not in the final output.</p> <p>At a recent Adobe "Create the Web" event (caveat: I work at Adobe), the Adobe Pipeline team opened <a href="http://www.youtube.com/watch?v=IiXnazocB30">its talk</a> about prototyping with this quote from Albert Einstein:</p> <blockquote><p>If I had an hour to solve a problem I'd spend 55 minutes thinking about the problem and 5 minutes thinking about solutions.</p></blockquote> <p>Einstein knew how to solve problems because he knew how to ask questions. Prototyping is not problem solving; it is the art of asking the right questions.</p> <p>I've spent a lot of my career building prototypes &mdash; writing code that oftentimes is never executed by a single user. Code that sometimes never even sees the light of day. It's a different kind of path compared to that followed by many software developers. On the one hand, it offers a large variety of interesting projects with short timelines, and on the other hand, the results are often ephemeral and rarely tangible.</p> <p>As such, prototype engineering requires a particular kind of personality and skillset. Firstly, you have to enjoy exploring designs, architectures and ideas perhaps more than you enjoy building products that see significant use. Secondly, you have to be willing and able to pick up new skillsets quickly, skimming the surface of a breadth of technologies while often forsaking depth of knowledge in any particular one.</p> <p>It is part of the prototype engineer's job to ensure that a prototype remains a prototype. This means to resist over-engineering and over-optimization. It means to push back on designs that are too high in fidelity, or ideas that are too broad in scope. It means working rapidly and pushing builds early and often. And it means continually refining your processes and skillsets to maximize your ability to know when to push forward, and know when to cut your losses and give up on an idea.</p> <p>The goals of prototyping are as varied as the organizations that produce them, but they nearly always seek to ask and answer questions like:</p> <ul> <li>Is the idea feasible?</li> <li>Will potential customers find it usable, useful and desireable?</li> <li>In what areas of design and production can we mitigate risk?</li> <li>What technology choices make the most sense?</li> <li>What design directions are most appropriate?</li> <li>Can the team work effectively together?</li> </ul> <p>Prototyping is a process of thinking through doing, and the only way to answer these questions is to do the work.</p> <p>Here are a few processes, skillsets and mindsets I've found worth cultivating as a prototype engineer. I can't say I always (or even often!) succeed in their application, but I certainly try.</p> <h2>Code Like a Sculptor</h2> <p>Software is called "soft" for a reason; it's malleable. When prototyping, code like a sculptor. Work roughly, using large approximations to get the "shape" of the idea. Build the entirety of a story from end to end (a skeleton application or what Dave Thomas calls a <a href="http://www.artima.com/intv/tracerP.html">tracer bullet</a>), then add and refine. It's important to come at prototyping from the standpoint that maybe it's not engineering at all, but instead a kind of play &mdash; a creative exploration of a problem space using the medium of code. At no point should any code you write for any prototype be considered sacred. Instead, all code should be eligible for deletion and refactoring at any time.</p> <h2>Cultivate a Beginner's Mind</h2> <p>Do not marry yourself to a particular technology or framework; approach each prototype as if you've never built anything like it before. Let go of all pre-conceived notions of what it means to build a web app or a tablet app or whatever you happen to be building, explore the range of possible options, then dive in. Be wary of ever labeling yourself as a "Rails developer," or a "JavaScript developer" or a "Cocoa developer." Just be a person willing to make (and break) things.</p> <h2>Work Outside In</h2> <p>Do not build more than you have to. More often than not, the goal of a prototype is to test the "feel" of a particular interaction model. Use mocks to fake the data layer. Use frameworks and boilerplate to get a skeleton built quickly. Focus the majority of your energy on the user interface, but don't polish early or as much as your design team would like you to. Chances are it's going to change. Instead continue returning to the 10,000ft. view of the UI. Can it work smoothly within the technological constraints of the chosen technology and platform? Does the flow make sense? Is it natural to implement? Let the UI guide the architecture; not the inverse.</p> <p>Part of the prototype engineer's job is to act as a designer. When you're "in the weeds" working deeply on implementing a particular idea, oftentimes you come to understand it better than other members of the team. If a design becomes difficult or cumbersome to implement in code, it may be because it's simply a bad design. Speak up and talk about it.</p> <h2>Use Source Control Effectively</h2> <p>Become friends with <a href="http://git-scm.com/">git</a>. Git's branching model makes experimentation easy and safe. When you're less afraid to just try something out, then you're more likely to do it.</p> <p>Create a git branch for every single tiny feature or idea you intend to implement. The smaller the branch scope, the more likely you are to remain focused. And because git asks you to name every branch at creation, it forces you to start every branch with intention and purpose. Think carefully with each "git branch" command: What is the question you are trying to ask? What is the problem you are trying to solve?</p> <h2>Test Early and Often</h2> <p>Testing allows for rapid and safe refactoring during pivots. While the testing overhead may mean you proceed more slowly in the beginning of a project, it also means that you can more quickly proceed in new design directions with less fear. It also forces you to keep your code <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>.</p> <p>This is perhaps the most difficult of these tips to stick with, for the simple reason that when prototyping you want to feel like you're moving quickly. Testing often feels superfluous when all you're testing is throw-away code. The goal, then, is to gain a sense of what's worth testing, and what's worth ignoring. Prototype testing is not about 100% test coverage; its about making you as nimble as possible. Usually this means light testing of the application core &mdash; things like data models, frequently used utility functions, helpers, or data layers &mdash; and avoiding the UI.</p> <h2>Prototype Your Process</h2> <p>Of course, not all of the above applies in every situation. Learn what works best for you and your team. Try out new processes and be willing to throw away old ones. Try out new tools and let go of tools that simply get in the way, even if they're the tools that "everybody uses."</p> <p>I've started to view my prototyping process less as an attempt to crystallize perfection, and more as a continually evolving practice of mastery. This is how I 've come to accept that it's OK to write throw-away code &mdash; even for most of my career. It's simply been my 55 minutes of thinking.</p>
id http://sean.voisen.org/blog/2012/10/thoughts-on-prototype-engineering
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2012/10/thoughts-on-prototype-engineering
title
Stomach Contents: Structure - struct
value Thoughts on prototype engineering
updated 2012-10-18T07:00:00Z
3
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>Small pieces loosely joined. It was the title of a book written by David Weinberger back in 2002, but one could say it&rsquo;s also become something of a mantra for software development for the 21st century. Good software is not monolithic; rather it is composed of small pieces, easily testable, loosely joined. At least, that&rsquo;s the present consensus.</p> <p><a href="http://www.chris-granger.com/2012/04/12/light-table---a-new-ide-concept/">Light Table</a> attempts to suffuse this idea at the core of the software development experience, reinventing what it means to edit code, presenting software not as a monolithic "project," but rather as a kind of visual web of functions. Code disembodied from the file. The ideas behind <a href="http://www.chris-granger.com/2012/04/12/light-table---a-new-ide-concept/">Light Table</a> are not new, but they&rsquo;re nevertheless still forward-thinking. With the growing popularity of dynamically-typed languages, the time is right to reinvent the entire programming experience from the ground up.</p> <p>Yet, I wonder if Light Table is radical <em>enough</em>. Nomenclature can lead the design process astray in mysterious ways; words both comprise and limit our thinking. IDE (integrated development environment) is one such word (ok well, it&rsquo;s a phrase really). Is there such a thing as a great IDE? In 15 years of software development, I&rsquo;ve yet to encounter one. The best is perhaps Visual Studio. Xcode and IntelliJ are just OK, and it all goes downhill from there. The problem with the IDE is that it&rsquo;s somewhat of a paradigmatic skeuomorphism, a monolith for developing software in the age of the web. We don&rsquo;t need more IDEs, and Light Table may do wise to avoid calling itself such.</p> <p>Consider: When a carpenter arrives at a house to build cabinetry, he doesn&rsquo;t arrive with a combination circular saw/hammer/nailgun/glue dispenser. He comes with a tool chest full of individual, special-purpose tools. Why should software development be any different? Rather than an IDE, how about a loose collection of special-purpose tools &mdash; a text editor, a function browser, a compiler, a search tool, a whatever &mdash; made easily available from a common "tool chest." This is no different than how any Unix-style command line works. And it&rsquo;s no different than how software development "used" to work (in the "heyday" of Vim and Emacs) before the IDE became the dominant paradigm. The difference being that the tool chest is smarter, and makes it easier to invoke said tools with fewer keystrokes than possible via the command line. And maybe, for those people who like icons and buttons, it&rsquo;s graphical too.</p> <p>Call it a LIDE &mdash; a Loosely Integrated Development Environment. Or simply, that collection of tools that just gets out of the way and lets us get our work done.</p>
id http://sean.voisen.org/blog/2012/04/loosely-integrated-development-environment
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2012/04/loosely-integrated-development-environment
title
Stomach Contents: Structure - struct
value Loosely integrated development environment
updated 2012-04-22T07:00:00Z
4
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>Perhaps it&rsquo;s not surprising, but Apple has <a href="http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=6658577.PN.&amp;OS=PN/6658577&amp;RS=PN/6658577">a patent</a> on the iconic "breathing" pattern used for the sleep indicator LED on all their computers.</p> <p>Recently &mdash; for a personal project &mdash; I wanted to see if I could replicate this effect. It turns out that I wasn&rsquo;t alone. Ladyada tried to <a href="http://www.adafruit.com/blog/2010/08/26/reverse-engineering-the-mac-breathing-led-2/">reverse engineer</a> the pattern a few years ago. Unfortunately, she stopped short of providing anything &mdash; like code &mdash; that the lazy web surfing Arduino hacker might use to recreate the effect. That&rsquo;s the purpose of this short tutorial.</p> <h2>Digging Into the Math</h2> <p>The Apple patent claims that the breathing pattern is a simple sinusoid, but observation of one&rsquo;s own (heavy) breathing will show that the pattern is a little more complicated than that. Maybe a sine wave works for Apple, but it doesn&rsquo;t look quite right to me. In my own breathing, I tend to ease in to a fast inhale, and stop suddenly before easing out to a fast exhale. Also, the period between inhalation and exhalation happens to be shorter than the period between exhalation and the next inhalation. This is not a simple sinusoid, as the <a href="http://static.flickr.com/62/212611654_4b3106a50b.jpg">oscilloscope plot</a> from Ladyada&rsquo;s own investigations will attest.</p> <p>A commenter on Ladyada&rsquo;s blog suggested that the pattern is probably more accurately modeled by f(x) = e<sup>sin(x)</sup>. Plotting this equation gives the following:</p> <p><img src="http://sean.voisen.org/images/breathing_pattern_1.gif" alt="Plot of exp(sin(x))" class="framed" /></p> <p>Compare the curvature characteristics of this plot with the simple sinusoid below:</p> <p><img src="http://sean.voisen.org/images/sinusoid.gif" alt="Plot of sin(x)" class="framed" /></p> <p>The plot of f(x) = e<sup>sin(x)</sup> has wider "troughs" (periods between inhale and exhale) and narrower "peaks" (periods between exhale and inhale), more accurately matching natural breathing patterns. As a simple experiment, try breathing "sinusoidally" and you&rsquo;ll see how unnatural it feels.</p> <h2>Turning it Into Code</h2> <p>For my own experimentation, I used the ubiquitous Arduino. The Arduino supports analog output using pulse-width modulation (PWM) mapped to integer values from 0 to 255. To recreate the breathing LED, this means manipulating the original equation f(x) = e<sup>sin(x)</sup> such that the amplitude fits within the PWM range.</p> <p>I took enough math in school to know that the minima and maxima of any equation occur at critical points in the equation, where the derivative of that equation is either 0 or its not differentiable. Beyond that, I left it to <a href="http://www.wolframalpha.com">Wolfram Alpha</a> to do the hard work. It turns out that the minimum of the wave occurs at 1 - e, and the maximum at e - 1/e. Using this information to adjust the amplitude of the equation such that it fits within the 0 to 255 range gives the following:</p> <p><img src="http://sean.voisen.org/images/breathing_equation.gif" alt="The final equation" /></p> <p>Swap <em>x</em> for the number of seconds that have elapsed, and map the above equation to PWM output on any supported Arduino pin, and you have the beginnings of a breathing pattern. The problem is that the frequency may be too high or low (depending on your preference), and so the breathing will appear fast or slow. Easy enough: Multiply <em>x</em> by any value to adjust the frequency. I like &pi;/2.</p> <p>Finally, 1 - e, and 255/(e - 1/e) are constants, and can be pre-calcuated to reduce overhead. The final Arduino sketch is as follows (with the LED connected to pin 11, a suitable resistor in series, yadda, yadda &hellip;):</p> <div class="highlight"><pre><code class="c"><span class="cp">#include &lt;math.h&gt;</span> <span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span> <span class="n">pinMode</span><span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="n">OUTPUT</span><span class="p">);</span> <span class="p">}</span> <span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span> <span class="p">{</span> <span class="kt">float</span> <span class="n">val</span> <span class="o">=</span> <span class="p">(</span><span class="n">exp</span><span class="p">(</span><span class="n">sin</span><span class="p">(</span><span class="n">millis</span><span class="p">()</span><span class="o">/</span><span class="mf">2000.0</span><span class="o">*</span><span class="n">PI</span><span class="p">))</span> <span class="o">-</span> <span class="mf">0.36787944</span><span class="p">)</span><span class="o">*</span><span class="mf">108.0</span><span class="p">;</span> <span class="n">analogWrite</span><span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="n">val</span><span class="p">);</span> <span class="p">}</span> </code></pre> </div> <h2>Gratuitous Video</h2> <p>And, in case you don&rsquo;t have an Arduino handy, here&rsquo;s a short video of the final effect:</p> <div class="video"> <iframe src="http://player.vimeo.com/video/31449253?title=0&amp;byline=0&amp;portrait=0&amp;color=cc0000" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe> </div> <h2>Conclusion</h2> <p>You might be asking: Is it really that big of a difference? Wouldn&rsquo;t a simple sinusoid suffice? To answer the latter question: yes. To answer the former: the difference is noticeable, but only slightly. Steve Jobs was a notorious perfectionist. I like to think that he would&rsquo;ve cared about such things.</p>
id http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino
title
Stomach Contents: Structure - struct
value Re-creating the "breathing" LED
updated 2011-10-31T07:00:00Z
5
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p><em>This is a <a href="http://sean.voisen.org/blog/2011/10/up-and-running-with-sifteo-sdk/">follow-up to a previous tutorial</a> on getting started with the Sifteo SDK. If you haven't at least managed to get the example applications from the SDK running, I suggest you start there first.</em></p> <h2>Introduction</h2> <p>Once you have the Sifteo SDK installed and working on your system, and you're ready to build your first game, you may find yourself asking: "Where do I go from here?"</p> <p>Moving from "Hello, World!" to real-life application development on a new platform is always a daunting task. To add to the challenge, consider the uniqueness and idiosyncrasies of the <a href="http://www.sifteo.com">Sifteo</a> platform:</p> <ol> <li><p><strong>The cubes are multi-faceted.</strong> Traditionally, software developers are accustomed to handling mouse clicks and keyboard input. A Sifteo cube is an entirely new I/O device with its own strengths, weaknesses, and quirks. The multi-faceted nature of the cube means that not only must you account for the four different sides of the cube, but also (depending on the complexity of your application) orientation, tilt, and adjacency to other cubes.</p></li> <li><p><strong>Communication with the cubes is wireless.</strong> The wireless connection is low-latency, but not zero-latency. Every command you send to the cubes (for instance, to draw a rectangle or paint an image) costs time, and too many commands can reduce the frame rate and introduce flicker. Furthermore, because the cubes are wirelessly connected, you must also account for any unexpected connectivity events that may happen. That is, cubes may be introduced to or removed from game play at any time.</p></li> <li><p><strong>Everything image displayed on the cubes is a raster graphic.</strong> All imagery, including text, that appears on the cubes must be an image or computationally drawn using the <code>Cube.FillRect</code> or <code>Cube.FillScreen</code> methods. Vectors don't exist, and there is no drawing API. Arbitrary text rendering is a particular challenge, and must be accomplished by generating sprite sheets of font glyphs and manually placing those glyphs to create words or sentences.</p></li> </ol> <p>Proper architecture and code organization will go a long way towards helping you overcome all of these challenges. In the process of developing "Lingua," my first Sifteo game, I've accumulated a small set of practices, tips and techniques, many of which I share here.</p> <h2>Architecture: Basic MVC</h2> <p>Certainly, there is no "one best way" to architect a Sifteo game, but there are good and bad ways. A bad way, of course, would be to shove everything in a single application class. A good way would involve developing a reasonable architecture based on an established design pattern. As far as patterns go, I like <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">MVC</a>.</p> <h3>Controllers</h3> <p>The Sifteo SDK includes <code>Sifteo.Util.StateMachine</code>, a handy class for managing control flow state that also happens to make it easy to assign controller classes to each state in your application. Notice that most games already in the Sifteo store proceed through a series of discrete states: title screen, options screen, a variety of game screens, possibly a pause or return to main menu screen, and so on. Using the <code>StateMachine</code> class, every screen can be a state, and every state can have its own controller. This is perhaps the easiest way to break up the logic of a small game into discrete classes.</p> <p>Consider a simple sorting game with three states as an example. You might set up the state machine in the main application class as follows:</p> <div class="highlight"><pre><code class="csharp"><span class="k">override</span> <span class="k">public</span> <span class="k">void</span> <span class="n">Setup</span> <span class="p">{</span> <span class="n">StateMachine</span> <span class="n">sm</span> <span class="p">=</span> <span class="k">new</span> <span class="n">StateMachine</span><span class="p">();</span> <span class="n">sm</span><span class="p">.</span><span class="n">State</span><span class="p">(</span><span class="s">&quot;Title&quot;</span><span class="p">,</span> <span class="n">titleController</span><span class="p">);</span> <span class="n">sm</span><span class="p">.</span><span class="n">State</span><span class="p">(</span><span class="s">&quot;Menu&quot;</span><span class="p">,</span> <span class="n">menuController</span><span class="p">);</span> <span class="n">sm</span><span class="p">.</span><span class="n">State</span><span class="p">(</span><span class="s">&quot;Game&quot;</span><span class="p">,</span> <span class="n">gameController</span><span class="p">);</span> <span class="n">sm</span><span class="p">.</span><span class="n">Transition</span><span class="p">(</span><span class="s">&quot;Title&quot;</span><span class="p">,</span> <span class="s">&quot;TitleToMenu&quot;</span><span class="p">,</span> <span class="s">&quot;Menu&quot;</span><span class="p">);</span> <span class="n">sm</span><span class="p">.</span><span class="n">Transition</span><span class="p">(</span><span class="s">&quot;Menu&quot;</span><span class="p">,</span> <span class="s">&quot;MenuToGame&quot;</span><span class="p">,</span> <span class="s">&quot;Game&quot;</span><span class="p">);</span> <span class="n">sm</span><span class="p">.</span><span class="n">Transition</span><span class="p">(</span><span class="s">&quot;Game&quot;</span><span class="p">,</span> <span class="s">&quot;GameToMenu&quot;</span><span class="p">,</span> <span class="s">&quot;Menu&quot;</span><span class="p">);</span> <span class="p">}</span> </code></pre> </div> <p>This results in a small state machine that allows you to move from title screen to menu, and back and forth between the menu and game states. This is, of course, a simplistic example &mdash; string literals should be made constants, the StateMachine should be a field, etc. &mdash; but this should illustrate the basic idea and allow you to get started.</p> <p>A few things to note about the <code>StateMachine</code> class:</p> <ul> <li>Every controller must implement the <code>IStateController</code> interface.</li> <li>The <code>OnTick</code> and <code>OnPaint</code> methods in the controllers will not be called unless you call the <code>Tick</code> and <code>Paint</code> methods on the StateMachine itself. I do this within the <code>Tick</code> and <code>Paint</code> methods in the main application class. (Though, because all control logic is in the controllers, I have never needed to call <code>Paint</code> from there.)</li> <li>Calling <code>Tick</code> on the StateMachine will call <code>OnTick</code> in every controller, whether it is the controller that currently owns control flow or not. You can check which state is currently in control by checking the <code>Current</code> property on the StateMachine.</li> </ul> <h3>Views</h3> <p>A common pattern found in many of the examples included in the SDK is to "wrap" each <code>Cube</code> instance in a kind of wrapper class. The wrapper contains the <code>Cube</code> through composition, and adds a reference to itself on the <code>userData</code> property of the cube itself. Cubes are typically wrapped on controller setup, or whenever they are discovered as the result of a <code>CubeSet.NewCubeEvent</code>.</p> <p>I like to think of these "wrappers" as view classes, and push all of my image manipulation and painting code to the wrappers themselves. This way, each wrapped cube is responsible for painting itself when commanded by the controller, and view code stays out of the controller. Likewise, in the controller you can listen to events from the cubes directly, or &mdash; better yet &mdash; re-dispatch them from the wrapper. Here's a sample wrapper:</p> <div class="highlight"><pre><code class="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">CubeWrapper</span> <span class="p">{</span> <span class="k">public</span> <span class="nf">CubeWrapper</span><span class="p">(</span><span class="n">Cube</span> <span class="n">cube</span><span class="p">)</span> <span class="p">{</span> <span class="n">Cube</span> <span class="p">=</span> <span class="n">cube</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="n">Cube</span> <span class="n">Cube</span> <span class="p">{</span> <span class="k">get</span><span class="p">{</span> <span class="k">return</span> <span class="n">cube</span><span class="p">;</span> <span class="p">}</span> <span class="k">set</span> <span class="p">{</span> <span class="n">cube</span> <span class="p">=</span> <span class="k">value</span><span class="p">;</span> <span class="n">cube</span><span class="p">.</span><span class="n">userData</span> <span class="p">=</span> <span class="k">this</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="k">public</span> <span class="k">void</span> <span class="nf">Paint</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// Painting code goes here</span> <span class="p">}</span> <span class="k">private</span> <span class="n">Cube</span> <span class="n">cube</span><span class="p">;</span> <span class="p">}</span> </code></pre> </div> <p>Once your wrappers have been defined, you can now loop through the cube set in the <code>OnSetup</code> method of your controllers, wrapping each cube as needed:</p> <div class="highlight"><pre><code class="csharp"><span class="k">public</span> <span class="k">void</span> <span class="nf">OnSetup</span><span class="p">(</span><span class="kt">string</span> <span class="n">transitionId</span><span class="p">)</span> <span class="p">{</span> <span class="k">foreach</span> <span class="p">(</span><span class="n">Cube</span> <span class="n">cube</span> <span class="k">in</span> <span class="n">CubeSet</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">cube</span><span class="p">.</span><span class="n">userData</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span> <span class="n">CubeWrapper</span> <span class="n">wrappedCube</span> <span class="p">=</span> <span class="k">new</span> <span class="n">CubeWrapper</span><span class="p">(</span><span class="n">cube</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p>It's possible, and likely, that different game states will have different painting code, in which case it's best to wrap and unwrap the cubes in the <code>OnSetup</code> and <code>OnDispose</code> methods in the controllers, respectively. <code>OnSetup</code> will be called whenever the state for that particular controller is entered, and <code>OnDispose</code> will be called before exiting that state.</p> <h3>Models</h3> <p>There's little to say about models except the fact that every application should have at least one. Because Sifteo games tend to be small, most data models will likely not be very complex. I tend to have a main application model, and sub-models that correspond with each controller. I've found it necessary for each cube wrapper to have a reference to its own model, or listen for events on its own dedicated model.</p> <p>To maintain loose coupling, models should dispatch events whenever a property changes that needs to be monitored, and the view should update accordingly. Presently, I don't do this. Instead, I look at the state of the model whenever the <code>Paint</code> method on my wrapper is called. Your milage may vary.</p> <h2>Architecture: Wiring It Together with Ninject</h2> <p>In any MVC architecture, controllers will need access to models and views, and views will likely need access to models (or events from models). There are myriad ways of resolving these dependency requirements &mdash; I prefer automated dependency injection. <a href="http://www.ninject.org">Ninject</a> is a light-weight, open-source dependency injector for .NET that seems well-suited for small-scale applications like Sifteo games.</p> <p>To get started with Ninject, simply <a href="http://ninject.org/download">download the Ninject.dll</a> and add it to the list of project references (just like the Sifteo.dll). Next, create (at least one) "module" that defines the main dependencies for your application. These may include not only models and controllers, but also any services and frequently-used helper classes. Continuing with the simple sorting game example, a module might look as follows:</p> <div class="highlight"><pre><code class="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">SortingGameModule</span> <span class="p">:</span> <span class="n">NinjectModule</span> <span class="p">{</span> <span class="k">public</span> <span class="k">override</span> <span class="k">void</span> <span class="nf">Load</span><span class="p">()</span> <span class="p">{</span> <span class="n">Bind</span><span class="p">&lt;</span><span class="n">SortingGame</span><span class="p">&gt;().</span><span class="n">ToSelf</span><span class="p">().</span><span class="n">InSingletonScope</span><span class="p">();</span> <span class="n">Bind</span><span class="p">&lt;</span><span class="n">GameModel</span><span class="p">&gt;().</span><span class="n">ToSelf</span><span class="p">().</span><span class="n">InSingletonScope</span><span class="p">();</span> <span class="n">Bind</span><span class="p">&lt;</span><span class="n">ILetterService</span><span class="p">&gt;().</span><span class="n">To</span><span class="p">&lt;</span><span class="n">LetterService</span><span class="p">&gt;().</span><span class="n">InSingletonScope</span><span class="p">();</span> <span class="n">Bind</span><span class="p">&lt;</span><span class="n">TitleController</span><span class="p">&gt;().</span><span class="n">ToSelf</span><span class="p">().</span><span class="n">InTransientScope</span><span class="p">();</span> <span class="n">Bind</span><span class="p">&lt;</span><span class="n">MenuController</span><span class="p">&gt;().</span><span class="n">ToSelf</span><span class="p">().</span><span class="n">InTransientScope</span><span class="p">();</span> <span class="n">Bind</span><span class="p">&lt;</span><span class="n">GameController</span><span class="p">&gt;().</span><span class="n">ToSelf</span><span class="p">().</span><span class="n">InTransientScope</span><span class="p">();</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p>And setup the <code>Main</code> function for your application like so:</p> <div class="highlight"><pre><code class="csharp"><span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span> <span class="n">Kernel</span> <span class="p">=</span> <span class="k">new</span> <span class="n">StandardKernel</span><span class="p">(</span><span class="k">new</span> <span class="n">SortingGameModule</span><span class="p">());</span> <span class="n">Kernel</span><span class="p">.</span><span class="n">Get</span><span class="p">&lt;</span><span class="n">SortingGame</span><span class="p">&gt;().</span><span class="n">Run</span><span class="p">();</span> <span class="p">}</span> <span class="k">public</span> <span class="n">IKernel</span> <span class="n">Kernel</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span> </code></pre> </div> <p>From this point forward, any depenencies defined in the <code>SortingGameModule</code> will be made available either through the <code>Kernel.Get</code> function, or &mdash; and more importantly &mdash; through the <code>[Inject]</code> attribute.</p> <p>For instance, you can inject the singleton <code>GameModel</code> into the <code>GameController</code> using constructor injection without ever passing an instance of the model into the controller manually:</p> <div class="highlight"><pre><code class="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">GameController</span> <span class="p">:</span> <span class="n">IStateController</span> <span class="p">{</span> <span class="na"> [Inject]</span> <span class="k">public</span> <span class="nf">GameController</span><span class="p">(</span><span class="n">GameModel</span> <span class="n">model</span><span class="p">)</span> <span class="p">{</span> <span class="n">GameModel</span> <span class="p">=</span> <span class="n">model</span><span class="p">;</span> <span class="p">}</span> <span class="k">private</span> <span class="n">GameModel</span> <span class="n">GameModel</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p>Ninject also supports other injection patterns, like property and method injection, though these practices are generally discouraged. For more information on using Ninject, try the <a href="https://github.com/ninject/ninject/wiki">Ninject wiki</a>.</p> <h2>Other Helpful Patterns</h2> <h3>CubeSet Injection</h3> <p>Oftentimes, I found that my controllers required a reference to the main application <code>CubeSet</code>. Because the <code>CubeSet</code> instance is a property of <code>BaseApp</code> it cannot be bound as for injection in the module likethe models, controllers, services, etc. In order to still make the <code>CubeSet</code> available for injection into my controllers, I created a custom method provider in the <code>Setup</code> function of my main application like so:</p> <div class="highlight"><pre><code class="csharp"><span class="k">override</span> <span class="k">public</span> <span class="k">void</span> <span class="nf">Setup</span><span class="p">()</span> <span class="p">{</span> <span class="n">Kernel</span><span class="p">.</span><span class="n">Bind</span><span class="p">&lt;</span><span class="n">CubeSet</span><span class="p">&gt;().</span><span class="n">ToMethod</span><span class="p">(</span><span class="n">context</span> <span class="p">=&gt;</span> <span class="n">CubeSet</span><span class="p">);</span> <span class="p">}</span> </code></pre> </div> <p>Once done, a CubeSet can be injected into a controller (or any other depenency listed in the module) using <code>Kernel.Get</code> or the <code>[Inject]</code> attribute as before.</p> <h3>State Machine Locking</h3> <p>The Sifteo <code>StateMachine</code> can be locked to a given state while transitions are queued up. This is useful, for instance, if you want to transition to a new state only after a sound finishes playing, or after a set number of ticks have elapsed. In the latter case, a dedicated <code>StateMachineLock</code> class has proven handy. This will lock the given <code>StateMachine</code> to its current state for a set number of ticks, and then dispose of the lock when finished. In use the lock's <code>Tick</code> method will need to be called from the <code>OnTick</code> method of the given controller:</p> <div class="highlight"><pre><code class="csharp"><span class="k">public</span> <span class="k">class</span> <span class="nc">StateMachineLock</span> <span class="p">{</span> <span class="k">public</span> <span class="nf">StateMachineLock</span><span class="p">(</span><span class="n">StateMachine</span> <span class="n">stateMachine</span><span class="p">)</span> <span class="p">{</span> <span class="n">StateMachine</span> <span class="p">=</span> <span class="n">stateMachine</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="n">StateMachine</span> <span class="n">StateMachine</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="kt">bool</span> <span class="n">Locked</span> <span class="p">{</span> <span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="n">unlockAt</span> <span class="p">&gt;</span> <span class="m">0</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="k">public</span> <span class="k">void</span> <span class="nf">LockForTickCount</span><span class="p">(</span><span class="kt">int</span> <span class="n">numTicks</span><span class="p">)</span> <span class="p">{</span> <span class="n">stateMachineLock</span> <span class="p">=</span> <span class="n">StateMachine</span><span class="p">.</span><span class="n">AquireLock</span><span class="p">();</span> <span class="n">unlockAt</span> <span class="p">=</span> <span class="n">numTicks</span><span class="p">;</span> <span class="n">tickCount</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="p">}</span> <span class="k">public</span> <span class="k">void</span> <span class="nf">Tick</span><span class="p">()</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(!</span><span class="n">Locked</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span> <span class="n">tickCount</span><span class="p">++;</span> <span class="k">if</span> <span class="p">(</span><span class="n">tickCount</span> <span class="p">&gt;=</span> <span class="n">unlockAt</span><span class="p">)</span> <span class="n">Unlock</span><span class="p">();</span> <span class="p">}</span> <span class="k">public</span> <span class="k">void</span> <span class="nf">Unlock</span><span class="p">()</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">stateMachineLock</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span> <span class="n">stateMachineLock</span><span class="p">.</span><span class="n">Dispose</span><span class="p">();</span> <span class="n">unlockAt</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="k">private</span> <span class="n">IDisposable</span> <span class="n">stateMachineLock</span><span class="p">;</span> <span class="k">private</span> <span class="kt">int</span> <span class="n">tickCount</span><span class="p">;</span> <span class="k">private</span> <span class="kt">int</span> <span class="n">unlockAt</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="p">}</span> </code></pre> </div> <h2>Conclusion</h2> <p>Though it's by no means exhaustive, I hope this small collection of tips and techniques will help a few developers in the nascent Sifteo development community.</p>
id http://sean.voisen.org/blog/2011/10/sifteo-development-mvc-ninject
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2011/10/sifteo-development-mvc-ninject
title
Stomach Contents: Structure - struct
value Sifteo development with MVC and Ninject
updated 2011-10-25T07:00:00Z
6
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>I&rsquo;m pretty excited about <a href="http://www.sifteo.com">Sifteo</a> cubes. I&rsquo;m even more excited about developing for them.</p> <p>If you&rsquo;re unfamiliar with Sifteo I recommend checking out the 2009 <a href="http://www.ted.com/talks/david_merrill_demos_siftables_the_smart_blocks.html">TED Talk</a> where early prototypes of Sifteo cubes were first introduced to the mainstream. Sifteo cubes represent an entirely new paradigm for playful learning through physical computing. They bring physicality and kinesthetic reasoning to educational gaming in a way that few other platforms can match.</p> <p>Recently, Sifteo released the first version of their SDK, allowing outside developers to begin exploring development for the Sifteo platform. As of the time of this writing, the Sifteo SDK is still an alpha release. As such, it is somewhat rough around the edges, with some crucial aspects of the documentation either lacking in necessary detail or missing entirely. This brief tutorial hopes to remedy that situation.</p> <h2>Introduction</h2> <p>Sifteo applications are developed in C# using the open source Mono framework. .NET developers should feel right at home, but developers familiar with Java, C++ or ActionScript should also have little trouble getting started.</p> <p>Before diving in, it is worth noting upfront that <strong>you do not need to own Sifteo Cubes to develop applications for them.</strong> The SDK ships with a desktop simulator called &ldquo;Siftulator&rdquo; that allows you to use your mouse to interact with virtual Sifteo cubes on the screen. You will still want real cubes for testing the interaction models of your applications (no virtual model can substitute for physical play), but the simulator will at least allow you to get started with no up-front cost. This simulator, being alpha, is still a bit clunky, but is also a valuable tool for rapid development. Without it, you must install your application on your physical cubes each time you want to test &mdash; a process that can take 30 seconds, a minute or more.</p> <h2>Getting Started</h2> <p>To follow along in this tutorial you&rsquo;ll need the following:</p> <ul> <li>A Mac running OS X 10.5+, or a Windows PC running XP or better</li> <li>The <a href="http://www.mono-project.com">Mono</a> runtime for your OS already installed</li> <li><a href="http://www.monodevelop.com">MonoDevelop</a>, the open source C# and .NET IDE</li> <li>The <a href="http://www.sifteo.com/developers">Sifteo SDK</a> itself, downloaded and unzipped to the location of your choosing. Throughout this tutorial I will refer to this location as <code>SDK_HOME</code>.</li> </ul> <h2>Creating a Project</h2> <p>The first step in creating a Sifteo project requires using the command-line tool <code>project_gen</code> from the Sifteo SDK to create a bare bones project structure.</p> <p>On Mac, the following incantation in the Terminal will create a new project called &ldquo;MyFirstApp&rdquo; in the current directory (make sure you&rsquo;re in a directory where you&rsquo;d like to store your projects):</p> <pre> mono [SDK_HOME]/tools/project_gen/project_gen.exe MyFirstApp </pre> <p>On Windows, use a similar command from the Mono command prompt, replacing &ldquo;/&rdquo; with &ldquo;\&rdquo;, etc. Some users on Windows have reported having to use the <code>-t</code> flag to specify the location of the project template, as in: <code>-t [SDK_HOME]/tools/project_gen/template</code>.</p> <h2>Opening Your Project</h2> <p>Once your project has been generated, open the <code>MyFirstApp.sln</code> file in MonoDevelop. Before you can build your project, you will need to update the project references to point to the <code>Sifteo.dll</code> file in the SDK distribution. Sifteo has unfortunately buried this file deep within the SDK directory hierarchy. To help make it easier to find, here is the location of the file for each operating system:</p> <p><strong>Mac:</strong> [SDK_HOME]/Siftdev.app/Contents/Resources/Runtimes/Mono/Current/sifteo/Sifteo.dll <strong>Windows:</strong> [SDK_HOME]\bin\Runtimes\Mono\Current\sifteo\Sifteo.dll</p> <p><img src="http://sean.voisen.org/images/sifteo_setup_1.png" alt="Set references in MonoDevelop" class="framed" /></p> <p><img src="http://sean.voisen.org/images/sifteo_setup_2.png" alt="Select Sifteo.dll" class="framed" /></p> <p>In order to avoid warnings at compile time, be sure to remove the broken reference to the Sifteo .NET assembly file that <code>project_gen</code> creates, leaving only the Sifteo.dll and System references.</p> <h2>Using Siftdev and Siftulator</h2> <p>You should now have a working empty application. Open up the Siftdev application from the SDK and select &ldquo;Load Apps ...&rdquo; from the Developer menu.</p> <p><img src="http://sean.voisen.org/images/sifteo_setup_3.png" alt="Select Load Apps in Siftdev" class="framed" /></p> <p>Select the root folder of your entire <code>MyFirstApp</code> project. The MyFirstApp application should now appear along with the rest of any games you have downloaded from the Sifteo store.</p> <p><img src="http://sean.voisen.org/images/sifteo_setup_4.png" alt="Select the MyFirstApp application" class="framed" /></p> <p>Select it and launch the Siftulator application from the SDK. Three cubes should show as connected in the status bar of Siftdev. (If you own real cubes, make sure the USB wireless transmitter is NOT connected, otherwise it will attempt to connect to your real cubes.)</p> <p><img src="http://sean.voisen.org/images/sifteo_setup_5.png" alt="Not connected" class="framed" /></p> <p><img src="http://sean.voisen.org/images/sifteo_setup_6.png" alt="Connected" class="framed" /></p> <p>By default the project is setup to connect to MonoDevelop for debugging. So, before you can play the application you must run the project from within MonoDevelop by selecting &ldquo;Run&rdquo; from the &ldquo;Run&rdquo; menu. Once you have done so, click Play in Siftdev and the application will begin running in Siftulator. A stream of logging information will appear in the Application Output panel within MonoDevelop.</p> <p>That&rsquo;s it! You&rsquo;ve built your first Sifteo application!</p> <h2>Using Sprites and Graphics</h2> <p>Getting graphics to work in the Siftulator requires a little more work. Note the following information from the API documentation:</p> <blockquote><p>Graphics on Sifteo cubes use an 8-bit color space of format RRRGGGBB. This color space maps to a fixed 256-color palette ... One color is reserved for the transparency key: RGB 72, 255, 170.</p></blockquote> <p>This means that any graphics you create for Sifteo must be converted to the proper color space and in the proper format.</p> <p>Siftdev includes a tool for exactly this purpose. It is called &ldquo;Image Helper&rdquo; and can be found under the Developer menu. Image Helper will convert images in PNG or JPEG format to the required .siftimg and .sftbndl formats in 8-bit color. As an example, download the following PNG strip of three 128x128px sprites. We will use it to display the letters ABC on three cubes, one letter per cube:</p> <p><img src="http://sean.voisen.org/images/LetterSprites.png" alt="Sample sprite strip" class="framed" /></p> <p>Create a folder <code>assets/images</code> within your MyFirstApp project and save the above PNG to that folder. Open Image Helper and select the PNG file using the &ldquo;Select File ...&rdquo; button. Then, click &ldquo;Convert.&rdquo; This will create a new file, <code>LetterSprites.siftimg</code> in <code>assets/images</code>. Next, click &ldquo;Select Folder ...&rdquo; and select the same <code>assets/images</code> folder, and under &ldquo;Save As&rdquo; give the new bundle the name &ldquo;Sprites.&rdquo; Finally, click &ldquo;Convert All.&rdquo;</p> <p><img src="http://sean.voisen.org/images/sifteo_setup_8.png" alt="Create a bundle" class="framed" /></p> <p>The <code>assets/images</code> folder should now contain four files in total:</p> <ul> <li>LetterSprites.png</li> <li>LetterSprites.siftimg</li> <li>Sprites_siftbndl_index.txt</li> <li>Sprites.sftbndl</li> </ul> <p>Modify the <code>Setup</code> function in <code>MyFirstApp.cs</code> and add the following code:</p> <div class="highlight"><pre><code class="csharp"><span class="k">override</span> <span class="k">public</span> <span class="k">void</span> <span class="nf">Setup</span> <span class="p">()</span> <span class="p">{</span> <span class="n">Log</span><span class="p">.</span><span class="n">Debug</span> <span class="p">(</span><span class="s">&quot;Setup()&quot;</span><span class="p">);</span> <span class="kt">int</span> <span class="n">spriteYPos</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="k">foreach</span> <span class="p">(</span><span class="n">Cube</span> <span class="n">cube</span> <span class="k">in</span> <span class="n">CubeSet</span><span class="p">)</span> <span class="p">{</span> <span class="n">cube</span><span class="p">.</span><span class="n">FillRect</span> <span class="p">(</span><span class="k">new</span> <span class="n">Color</span> <span class="p">(</span><span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">255</span><span class="p">),</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">Cube</span><span class="p">.</span><span class="n">SCREEN_WIDTH</span><span class="p">,</span> <span class="n">Cube</span><span class="p">.</span><span class="n">SCREEN_HEIGHT</span><span class="p">);</span> <span class="n">cube</span><span class="p">.</span><span class="n">Image</span> <span class="p">(</span><span class="s">&quot;LetterSprites&quot;</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="n">spriteYPos</span><span class="p">,</span> <span class="n">Cube</span><span class="p">.</span><span class="n">SCREEN_WIDTH</span><span class="p">,</span> <span class="n">Cube</span><span class="p">.</span><span class="n">SCREEN_HEIGHT</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">);</span> <span class="n">cube</span><span class="p">.</span><span class="n">Paint</span> <span class="p">();</span> <span class="n">spriteYPos</span> <span class="p">+=</span> <span class="n">Cube</span><span class="p">.</span><span class="n">SCREEN_HEIGHT</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> </code></pre> </div> <p>Everything should now run as expected on real cubes. For Siftulator to correctly display the sprite images, however, it needs to be directed to the location of the folder containing the individual .siftimg files. Select the second-to-last button in Siftulator toolbar and select the <code>assets/images</code> folder in your project. Finally, run your project in Siftulator (you may need to reload the application in Siftdev from the developer menu). The output should look something like the following:</p> <p><img src="http://sean.voisen.org/images/sifteo_setup_9.png" alt="Final application" class="framed" /></p> <h2>Conclusion</h2> <p>This is, of course, the bare-bones minimum a developer needs to know to start creating games and applications for Sifteo. But hopefully it will help the few early adopters out there who struggled, as I did, to fill in some of the holes in the existing SDK documentation on how to set up your development environment.</p> <p>The SDK does include in-depth API documentation, as well as a few examples coded in <a href="http://en.wikipedia.org/wiki/Literate_programming">literate programming</a> style, that are certainly worth exploring for information on sound, the event architecture, persisting data, and more.</p> <p>Happy sifting :)</p>
id http://sean.voisen.org/blog/2011/10/up-and-running-with-sifteo-sdk
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2011/10/up-and-running-with-sifteo-sdk
title
Stomach Contents: Structure - struct
value Up and running with the Sifteo SDK
updated 2011-10-04T07:00:00Z
7
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p style="text-align:center;"><small>(This post is also available in <a href="http://science.webhostinggeeks.com/zasto-haskell">Serbo-Croatian</a>. Translation by Jovana Milutinovich.)</small></p> <p>I&rsquo;m learning <a href="http://www.haskell.org">Haskell</a>. Maybe you should too. Here&rsquo;s why:</p> <p>Every programmer has something to say on what other programmers should know in order to be standouts in their field. Back in 2004, for instance, when Python was more obscure than it is now, Paul Graham wrote an essay about something he called the <a href="http://www.paulgraham.com/pypar.html">Python paradox</a>. In that essay, Graham summarized the paradox as follows:</p> <blockquote><p>&hellip; if a company chooses to write its software in a comparatively esoteric language, they&rsquo;ll be able to hire better programmers, because they&rsquo;ll attract only those who cared enough to learn it &hellip; [Thus] the language to learn, if you want to get a good job, is a language that people don&rsquo;t learn merely to get a job.</p></blockquote> <p>I won&rsquo;t go into the details of Graham&rsquo;s reasoning behind the paradox (you can read the essay for that), but I think it has legs. The best programmers are those who love their craft &mdash; the ones who love it so much they&rsquo;ll learn unpopular languages just for the fun of it. Simple enough. As an addendum to Graham&rsquo;s advice, however, I&rsquo;d add the following: The best programmers should also have a high- or expert-level competence in at least one language from each of the three following groups: the large-scale object-oriented languages (Java, C++, C#, ActionScript, etc.), the dynamically-typed &ldquo;scripting&rdquo; languages (Ruby, Python, Perl, etc.), and the functional languages (Scheme, OCaml, Haskell, Clojure, F# and friends).</p> <p>Thus, if you&rsquo;re going to learn a new language, pick one from the group that is least represented in your repertoire. If you&rsquo;re like me, this means the language to learn is a functional language. An esoteric functional language. Yes, it&rsquo;s time to leave your comfort zone.</p> <p>At the beginning of 2011, I decided to make Haskell my programming language of the year. This was not without significant deliberation. Learning a new language requires a substantial investment of time and mental energy. And Haskell is certainly not the most popular functional language. (Clojure and Scala &mdash; both of which run on the JVM &mdash; have seen a rapid surge of popularity as of late.) But I don&rsquo;t learn new things simply to retain employment. I learn them because they&rsquo;re interesting. Here&rsquo;s why I found Haskell to be the most interesting of them all:</p> <h3>Elegance</h3> <p>Syntax matters, and I prefer to write in a language that looks and feels elegant. Elegance was the allure of Ruby when a first started learning it five years ago. Elegance is the allure of Haskell for me now. Certainly there are different types of elegance. Lisp and its kin (Scheme, Clojure) are elegant in their simplicity (everything&rsquo;s a list!), but not in brevity. I&rsquo;m happy to learn more syntax if it means I type less (and don&rsquo;t have to manage parentheses). And I like languages that allow syntactic variations for accomplishing the same task. As Larry Wall, the creator of Perl, <a href="http://world.std.com/~swmcd/steven/perl/linguistics.html">notes</a>, syntactic variety has an anthropological analogue in human languages. Perhaps that&rsquo;s why, at least to me, the weird syntactic nooks and crannies, and &ldquo;polyexpressiveness&rdquo; of languages like Ruby and Haskell just feel right. That, and it&rsquo;s just more fun.</p> <p>The canonical example used to illustrate Haskell&rsquo;s elegance is quicksort. Here it is (<a href="http://www.haskell.org/haskellwiki/Why_Haskell_matters">original source</a>):</p> <div class="highlight"><pre><code class="haskell"><span class="nf">qsort</span> <span class="kt">[]</span> <span class="ow">=</span> <span class="kt">[]</span> <span class="nf">qsort</span> <span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="n">qsort</span> <span class="n">less</span> <span class="o">++</span> <span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">++</span> <span class="n">qsort</span> <span class="n">more</span> <span class="kr">where</span> <span class="n">less</span> <span class="ow">=</span> <span class="n">filter</span> <span class="p">(</span><span class="o">&lt;</span><span class="n">x</span><span class="p">)</span> <span class="n">xs</span> <span class="n">more</span> <span class="ow">=</span> <span class="n">filter</span> <span class="p">(</span><span class="o">&gt;=</span><span class="n">x</span><span class="p">)</span> <span class="n">xs</span> </code></pre> </div> <p>Four lines! And it reads just like how you would describe the algorithm: A list is sorted if all the elements smaller than the front of the list are moved to the front list (and sorted), and all the elements greater than the front are moved to the end (and sorted).</p> <h3>Laziness</h3> <p>There are few areas of life where laziness can be considered a virtue. Computation is one of them. Haskell is lazy in the sense that it only evaluates code when it&rsquo;s absolutely necessary &mdash; allowing you to avoid wasting precious CPU cycles. And make use of some fairly nifty code tricks, like using infinitely long lists. Consider the following:</p> <div class="highlight"><pre><code class="haskell"><span class="nf">take</span> <span class="mi">10</span> <span class="o">$</span> <span class="n">filter</span> <span class="n">even</span> <span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="p">]</span> </code></pre> </div> <p>This will result in a list consisting of the first 10 even integers from 0 to infinity. Because Haskell is lazy, it will never try to create an infinite list (impossible anyway), but only create the elements of the list it actually needs.</p> <p>Consider also <a href="http://stackoverflow.com/questions/265392/why-is-lazy-evaluation-useful">this example</a> based on quicksort from above:</p> <div class="highlight"><pre><code class="haskell"><span class="nf">minimum</span> <span class="n">list</span> <span class="ow">=</span> <span class="n">head</span> <span class="o">$</span> <span class="n">qsort</span> <span class="n">list</span> </code></pre> </div> <p>This defines a function that gets the smallest element of a quicksorted list. In a non-lazy language, the entire list would be sorted first, then the head (the first element) of that sorted list would be returned. That&rsquo;s a lot of wasted work. In Haskell, the list is only sorted enough to give the correct answer, and that means you only need to sort the elements that are lesser in value than the first element of the original list.</p> <h3>Purity</h3> <p>Like all functional languages, Haskell has no <a href="http://en.wikipedia.org/wiki/Side_effect_(computer_science">side-effects</a>. Side-effect free programming is rapidly becoming a necessity as we move to writing code that runs well on multiple cores. It also means fewer bugs. Purity is where it&rsquo;s at in the 21st century. And unlike some other functional languages, Haskell pursues purity as strictly as possible. &ldquo;Pure&rdquo; code and &ldquo;impure&rdquo; code (like code used for IO) remain neatly and permanently separated (through the use of monads) so that you can continue to reason about your pure code without it being &ldquo;tainted&rdquo; by side-effects.</p> <h3>Type inference</h3> <p>Type inference permits all the benefits of strong typing without all the typing (no pun intended). This means that you get type safety, without having to explicitly declare the types of everything (unless you want to). The Haskell compiler is smart enough to infer what the types of things should be, and you can continue to code on your merry way knowing that the compiler has got your back.</p> <p>Coming from languages like ActionScript and Java, this is perhaps one of my most favorite features of Haskell. The amount of key banging it saves is enormous, and the code looks as simple and elegant as any dynamically typed language.</p> <h3>Getting Started</h3> <p>By far the best resource for getting started with Haskell is the freely available book, <a href="http://learnyouahaskell.com/">Learn You a Haskell for Great Good</a>. It&rsquo;s friendly, approachable, and easy to follow. Those coming from the Ruby community will find it reminiscent of the playful style of <a href="http://mislav.uniqpath.com/poignant-guide/">_why&rsquo;s Poignant Guide to Ruby</a>. I can&rsquo;t recommend it enough.</p> <p>Those looking for something more traditional may prefer the (also freely available) <a href="http://book.realworldhaskell.org">Real World Haskell</a>. It&rsquo;s another great book from O&rsquo;Reilly, but not nearly as fun.</p> <p>&nbsp;</p> <p>Learning Haskell may not get you a job programming in Haskell, but as Paul Graham postulates, it may still get you a job. Personally, I find that irrelevant. Learning the language has proven to be fun and rewarding and I plan to continue my Haskell adventures into 2012.</p>
id http://sean.voisen.org/blog/2011/09/why-haskell
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2011/09/why-haskell
title
Stomach Contents: Structure - struct
value Why Haskell?
updated 2011-09-04T07:00:00Z
8
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p><a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882">Clean code</a> is all the rage these days. It&rsquo;s what all the cool kids are doing. Which is a bit odd, because you would think that clean code should never have been a fad, but rather a staple of software development since the earliest days of FORTRAN. Such is not the case.</p> <p>Instead, it took the recent rise in popularity of dynamically typed languages like Ruby and Python to make test-driven development (TDD) &mdash; and clean code by extension (or is it vice-versa?) &mdash; fashionable. Mostly out of sheer necessity. If you don&rsquo;t have a compiler to tell you when you made a mistake as simple as a misspelled variable name, you better have a suite of tests that will.</p> <p>I&rsquo;m guessing here, but I get the sense that in the software industry TDD is still the exception rather than the rule. Why? Some software developers might say it comes down to a matter of priorities. Software companies prioritize ship dates and over quality. And writing fully tested code cleanly takes time &mdash; time which developers don&rsquo;t have. This results in code that you might generously call &ldquo;quick and dirty.&rdquo; In fact, in software development, &ldquo;quick&rdquo; and &ldquo;dirty&rdquo; are two adjectives you always find paired together. Like light and shadow, or peas and carrots, or Batman and Robin, or C and buffer overflows, where you find one you find the other. The rule is: code written quickly is by necessity sloppy. And, conversely, clean code takes time.</p> <p><a href="http://en.wikipedia.org/wiki/Robert_Cecil_Martin">Uncle Bob</a>, however, says otherwise. In order to go fast, your code has to be clean and it needs to have full test coverage. If it does not, you&rsquo;ll spend too much time fixing bugs that could&rsquo;ve been caught with a proper test suite or made easier to find with proper naming conventions. And you&rsquo;ll waste hours or days accidentally breaking the functionality of existing code when you try to refactor or add new features.</p> <p>Recently, our team at Adobe XD invited Uncle Bob over to our office to spend three full days beating this philosophy into our craniums. Since then, a few of us have been practicing employing clean code techniques in our day-to-day projects. I&rsquo;ve been sticking to it as rigorously as possible. A few takeaways from my own experience:</p> <ul> <li><p><strong>TDD is faster in the long-run, not the short-run.</strong> There&rsquo;s no way around the fact that writing tests requires an upfront time commitment. But oftentimes the cost is worth it. Especially when it comes time to implement the next feature and you discover that &mdash; thanks to lack of forethought &mdash; code you just wrote needs to be refactored or re-architected. Suddenly re-architecture feels like no big deal. Well ... except that you often also have to modify all your tests in the process.</p></li> <li><p><strong>I&rsquo;ve found that I don&rsquo;t need log statements.</strong> I used to do this all the time &mdash; sprinkle trace/log/printf statements throughout my code as a sanity check to ensure execution flow was correct. Now, log statements have become a rarity. I know the execution flow is correct; the tests say so.</p></li> <li><p><strong>I almost never find myself in the debugger.</strong> I&rsquo;m not a fan of using debuggers anyway, except when tackling very serious bugs that can&rsquo;t be quashed by other means. Debuggers require too much work, overhead and tedium when often a simple trace statement will give you all the information you require. Thankfully, so far, with TDD I have yet to need one at all.</p></li> <li><p><strong>A good suite of tests is like a pre-programmed <a href="http://en.wikipedia.org/wiki/Read-eval-print_loop">REPL</a>.</strong> Which is great if the language you are working with doesn&rsquo;t have one (and ActionScript does not). It offers a convenient framework for trying out small ideas in a pain-free way, the same way you might if you did have a REPL, but without all the repetitive typing.</p></li> <li><p><strong>In non-interpreted languages, TDD works best when you have a decent compiler.</strong> As a developer at Adobe XD, I currently work with ActionScript much of the day, and mxmlc is painfully slow. Running tests is a bear because it takes so long to compile the test suite. Comparatively, test compilation in Java is lightning quick and a pleasure to work with. And Ruby&rsquo;s <a href="http://relishapp.com/rspec">RSpec</a> is even more of a joy to use.</p></li> </ul> <p>Writing tests is not fun. Anyone who tells you otherwise is a liar. But, getting tests to pass is surprisingly addictive. And therein lies the power of TDD: it offers a kind of IV drip of continous daily victories.</p> <p>But would I use TDD for every project I work on? Probably not. For personal &ldquo;one-off&rdquo; projects or projects I know will not see much future maintenance, the slower development time is simply not worth it. For serious, long-term projects however, TDD is now a must.</p> <h3>Responses</h3> <ul> <li>My friend Daniel Wanja <a href="http://www.onrails.org/2011/08/30/writing-tests-is-not-fun-anyone-who-tells-you-otherwise-is-a-liar">takes issue with me calling him a liar</a> :)</li> </ul>
id http://sean.voisen.org/blog/2011/08/thoughts-on-test-driven-development
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2011/08/thoughts-on-test-driven-development
title
Stomach Contents: Structure - struct
value Thoughts on test-driven development
updated 2011-08-28T07:00:00Z
9
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <blockquote><p>“Nothing is less real than realism … Details are confusing. It is only by selection, by elimination, by emphasis, that we get at the real meaning of things.” — Georgia O’Keeffe</p></blockquote> <p><a href="http://www.okeeffemuseum.org/biography.html">Georgia O’Keeffe</a> lived in the high deserts of Northern New Mexico; the environment served and supported her philosophy. The desert is a place uncluttered, without distraction, a place to think.</p> <p>We all need this. Where is your desert?</p> <p>Inspired by what I read a few weeks ago in <a href="http://focusmanifesto.com/">Leo Babauta’s manifesto on simplicity</a>, entitled Focus, I’ve been slowly eliminating distraction from my own life. A minimalist at heart, I’ve always been drawn to sparse environments. Yet, it has required considerable encouragement and inspiration for me to take the radical measures necessary to simplify in a meaningful way. In the 21st century, clutter has a way of seeping in.</p> <p><img src="http://sean.voisen.org/images/workspace_032011.jpg" alt="My desk" class="framed" /></p> <p>Above is a photo of my current workspace. One small standing desk. Intentionally too small, in fact, to become a resting place for errant papers or objects. Papers are digitized using the scanner on the right, and then immediately discarded (recycled). A large cinema display sits atop the desk, devoid of icons. The only item on my virtual desktop is a list of the three most important tasks I’ve set out to accomplish for the day. No chair. Standing improves my posture, encourages me to take breaks more frequently, and has proven to be better for my overall health. Very few adornments on the walls. A calendar, some photos from our wedding, a few hard-earned diplomas.</p> <p>In contrast, my previous workspace included two desks, a chair, racks of electronics components, a desk lamp, geeky trinkets of all sorts (Legos, Rubik’s cube, etc.), a soldering iron, various framed photos, and at least one tenacious stack of papers I could never find time to file away. And many other itinerant objects as well.</p> <p>Ridding myself of this stuff was both liberating and difficult. Liberating, in that my work environment now encourages me to focus only on what I have deemed most important to me: writing and programming. Difficult, in that I was more attached to that other stuff (and the activities associated with it) than I realized.</p> <p>Elimination requires practice and courage, but it is one of the most necessary skills of our day. It’s the only way we can focus on what is most meaningful to us. It’s the only way we can become great at what we do. O’Keeffe achieved worldwide renown as an artist because she honed her ability to eliminate the unnecessary to a razor-sharp edge. There is never anything “extra” in her work. There is nothing superfluous. If we, too, are to make our lives a work of art, then we could do worse than to aspire to be like one of O’Keeffe’s paintings.</p>
id http://sean.voisen.org/blog/2011/03/workspace-focus
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2011/03/workspace-focus
title
Stomach Contents: Structure - struct
value Workspace focus
updated 2011-03-20T07:00:00Z
10
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <blockquote><p>“From one gut feeling I derive much consolation: I suspect that machines to be programmed in our native tongues — be it Dutch, English, American, French, German, or Swahili — are as damned difficult to make as they would be to use.” — <a href="http://www.cs.utexas.edu/users/EWD/transcriptions/EWD06xx/EWD667.html">E.W. Dijkstra</a></p></blockquote> <p>If you look around at the world of programming languages, you’ll notice that much hasn’t changed in the last 20 or 30 years. The scenery has shifted, sure — new languages have come into vogue, others have gone out of style — but the fundamental paradigms of programming language design haven’t evolved much since Smalltalk. Consider, for instance, that C-style object-oriented programming still dominates the software industry — whether it be C++, Objective-C, Java, C#, or ECMAScript and its progeny. This family of languages has been dominant for decades and shows no signs of relinquishing its dominant position any time soon. The question is: Why? On one hand you have C, essentially a glorified assembly language, so impoverished in its expressiveness it takes myriad lines of code to say anything. And on the other hand you have “modern” languages like Java and C#, so dominated by rigid ontological structure and type systems that they have become a kind of bureaucratic nightmare.</p> <p>These are the primary tools that we as programmers and software developers use to express our ideas, so one would think that we’d clamor for something better. One would think that we’d desire languages that are far more expressive and far less-constraining; tools that allow us to express our ideas as we think them, rather than as the computer requires them to be expressed. Programming languages where the computer better understands what we mean, not just what we say.</p> <p>One would think …</p> <p>Making good software is hard. Part of the reason it’s so hard is that the tools we have for making software are still pretty darn awful. Writing enterprise software in, say, C++, is akin to attempting to write Anna Karenina using a third-grader’s vocabulary. You can tell the story, but it’s going to take a lot more words to say it.</p> <p>The most expressive languages on the planet are natural human languages. We have something to learn by studying them. Of course, this doesn’t mean that the ultimate panacea for our software development woes is to start programming in plain English. I agree with Dijkstra on this: such is a path fraught with disaster. Languages that historically have attempted to walk this path have never gained much traction. AppleScript, for instance, (like HyperTalk before it) has its adherents, but most find it too cumbersome and verbose to bother learning. There is a fine line between expressiveness and tedium.</p> <p>Instead, perhaps what we need is more of the flexibility and expressiveness of natural language to find its way into programming. Take Perl. Some people call Perl an abomination. I’m not going to argue. But there are <a href="http://world.std.com/~swmcd/steven/perl/linguistics.html">a few design principles that Larry Wall got right</a>:</p> <ul> <li><strong>Say it how you want to say it:</strong> Just as in natural languages, in programming languages there should be more than one way to say the same thing. I say, “take a walk,” you say, “go for a stroll.” They mean the same thing, and since programming is ultimately an act of describing behavior (we’re not writing poetry), meaning is what matters. Some may argue that this kind of “polyexpressiveness” impedes software maintainability. If one programmer solves a problem with some form of obscure syntax, the next programmer may have difficulty understanding it. There are at least two counter-arguments: One, the constraints of a programming language should not define your chosen best-practices. Let languages be about freedom; let the community or development team decide how these freedoms may be exercised. Two, the gain in productivity afforded by being able to think about a problem in multiple ways more than offsets loss caused by having to learn syntax. Learning new things is good for you.</li> <li><strong>Ambiguity is not a sin:</strong> There is power in ambiguity. Consider, for instance, the argument that more (dynamically-typed) programming languages should support pronouns – namely, the ability to refer to the result of a previous calculation as “that” or “it.” Perl is one of few programming languages that supports pronouns, the famous (or infamous), $<em> and @</em>. Pronouns keep local code DRY while simultaneously allowing the programmer to better focus on ideas instead of spelling and syntax and unnecessary naming. Nevertheless, they should not be included at the cost of readability. I’m no fan of Perl’s use of implicit pronouns (called “topicalization”). They largely render code unreadable. But explicit pronouns are just fine.</li> <li><strong>Support inevitable divergence:</strong> As Wall writes, “Because a language is designed by many people, any language inevitably diverges into dialects. It may be possible to delay this, but for any living language the forces of divergence are nearly always stronger then the forces of convergence.” Why not build support for dialects into a programming language? It promotes experimentation, community contribution, allows for dialects to flourish without detracting from the language core. Sticklers for standards may find this appalling, but if dialects are modular – like plug n’ play domain specific languages – there’s really no good reason not to like them. The best ideas in new dialects may soon find themselves part of the language standard. E4X, for instance, started out as a domain-specific ECMAScript dialect in WebLogic that now finds (fairly) wide support.</li> </ul> <p>Larry Wall is a linguist, so while that may not have enabled him to be the world’s most popular programming language designer, it did allow him to approach language design from an entirely different perspective. We need more of this. The challenge with programming languages today is that they’ve all been designed solely by programmers and computer scientists, people far too enmeshed in existing paradigms to think differently. And we desperately need to think differently. Because when it comes to programming languages, I think we can do much, much better.</p>
id http://sean.voisen.org/blog/2011/02/thoughts-on-programming-language-expressiveness
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2011/02/thoughts-on-programming-language-expressiveness
title
Stomach Contents: Structure - struct
value Thoughts on programming language expressiveness
updated 2011-02-21T08:00:00Z
11
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>Recently, I finished reading <a href="http://www.gigamonkeys.com/">Peter Seibel’s</a> <a href="http://www.amazon.com/Coders-Work-Reflections-Craft-Programming/dp/1430219483">Coders at Work</a>. If you’re a programmer interested in the history and critique of your craft, here’s a book worth perusing. Coders at Work is a collection of fifteen interviews with some of the most “famous” or “interesting” programmers alive today. I wrap “famous” and “interesting” in scare quotes because they’re subjective terms at best – especially in as diverse a field as computing – so perhaps “programmers who have achieved renown whilst working on high-profile projects” is a more accurate description of those in question. For instance, though I’d only personally heard of at least seven of the book’s fifteen interviewees, of the seven, only three – Donald Knuth, Peter Norvig and L. Peter Deutsch – had I any significant acquaintance with their writings or work. Nevertheless, fame or fortune notwithstanding, those interviewed in the book are programmers with decades of wisdom and experience (well, except maybe Brad Fitzpatrick), and it’s certainly worth considering their stories, advice and opinions. At the very least, if only to learn what not to do. (Oh, and how painful it was to be a programmer in the days of punch cards.)</p> <p>Because it’s a collection of transcribed interviews, there’s really no legitimate reason to read Coders at Work linearly from cover to cover. In fact, if you do pick up this book, I wouldn’t recommend doing so (though, ill-informed as I was, that’s exactly what I did). Instead, it’s probably best to cherry-pick chapters on a whim. The reason for this is simple: redundancy. One of the more interesting attributes of Coders at Work is also its greatest weakness: the astonishing consensus of opinion on a wide group of topics from such a diverse group of programmers. On issues as far ranging as a language design, job interview strategies, computer science books worth reading, code readability and formatting, debugging strategies, and how to classify programming as craftsmanship, science, engineering or art, there is remarkable similarity of response. While not all of the fifteen ever completely agree on anything — in fact, in some instances there’s quite polarized disagreement — generally the redundancy of advice and information renders itself simultaneously enlightening and tiresome.</p> <p>Here’s a summary of what I gleaned to be the majority opinion on a few of the less-divisive topics:</p> <ul> <li><strong>Code is, first and foremost, for people to read.</strong> This is probably the most common assertion made by nearly every interviewee in the book, and it was heartening to hear if only because it reinforced my own beliefs on the matter. Good programmers have to be good writers, because programming is as much an act of communication as it is of problem solving. Anybody can write code that a computer can understand, but few can write code that is also easily comprehensible by another human. Write appropriate comments. Use well-named variables. Keep a thesaurus handy.</li> <li><strong>Puzzles in job interviews are generally worthless.</strong> This was another theme reiterated throughout the book. Forget the silly hoops that the folks at some large software shops — like Google and Microsoft — make all those poor fresh college grads jump through. It’s far better to get a sense of the interviewee’s programming style, personality, critical thinking skills, and aptitude for curiosity than to award a job based on his or her ability to solve some random puzzle. C++ is a bad language. Personally, I hate C++ and I was glad to hear that I was in good company with my distaste for the language. Almost nobody interviewed in Coders in Work had anything good to say about C++. <a href="http://en.wikipedia.org/wiki/Jamie_Zawinski">Jamie Zawinski</a>, for instance, called it an “abomination.” And even <a href="http://en.wikipedia.org/wiki/Ken_Thompson">Ken Thompson</a> described it as “a garbage heap of ideas that are mutually exclusive.” (Peter Seibel has a more <a href="http://gigamonkeys.wordpress.com/2009/10/16/coders-c-plus-plus/">thorough list of interview quotes</a> on the design flaws and challenges of working with C++.)</li> <li><strong>If you’re going to get only one book on computer science or programming, get Donald Knuth’s <a href="http://www.amazon.com/Art-Computer-Programming-Volumes-Boxed/dp/0201485419/">The Art of Computer Programming</a>.</strong> Knuth’s classic set of volumes was cited again and again as worth reading. Ironically, almost nobody had actually done that. And even fewer said that the math contained therein was truly worth the average developer’s time to trudge through. A bit contradictory, if you ask me. Yes, The Art of Computer Programming may not be the best choice for light weekend reading, but Knuth’s volumes on algorithms and data structures certainly are valuable reference material. And allowing them to collect dust on your shelves will make you look smart.</li> <li><strong>Programming is mostly a mix of craftsmanship and art.</strong> Most interviewees rejected the idea that science has much of a role to play in computer programming — or even computer science itself — and few were willing to use the term “engineering” when describing their work. Instead, they almost unanimously gravitated towards the word “craft.” <a href="http://en.wikipedia.org/wiki/Joshua_Bloch">Josh Bloch</a> called it an “aesthetic pursuit.” The downplay of the role of “science” and “engineering” in day-to-day programming was quite humbling, and many interviewees seemed to have high levels of respect for those who engage in “real” science and engineering.</li> </ul> <p>Of course, this is only the tip of the iceberg and Coders at Works covers much more than this. If anything, I’d say what I got most of the book was inspiration. Yes, the current state of modern software is disheartening. Yes, it’s too complex, too inflexible, too massive, too unreliable, too unfriendly, too riddled with bugs. But the field is young and there’s still hope. Here’s a group of people who have made significant contributions to solving these problems simply by following their passion. Maybe we can too.</p> <p>But first things first: we need to stop calling ourselves “coders.”</p>
id http://sean.voisen.org/blog/2010/12/coders-at-work
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2010/12/coders-at-work
title
Stomach Contents: Structure - struct
value Coders at work
updated 2010-12-05T08:00:00Z
12
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>With the introduction of Adobe AIR 2.5 and AIR for Android, the AIR API gains a new class: <a href="http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/media/StageWebView.html">StageWebView</a>. StageWebView can best be described as HTMLLoader’s younger and less-capable step-brother, designed for mobile devices (though it also works in desktop AIR). Like HTMLLoader, StageWebView provides developers with a means to display HTML content — both local and remote — in an AIR application. Unlike HTMLLoader, however, developers cannot add StageWebView instances to the display list. Instead, StageWebView literally draws an instance of the device’s native WebView on top of the stage using designated viewport coordinates and boundary dimensions. This means that, at least presently, developers cannot draw or otherwise place display list objects on top of a StageWebView instance, and animating StageWebView instances proves difficult and exhibits fairly poor performance. StageWebView also does not offer alpha channel support. Nor does it offer a straightforward JavaScript to ActionScript communications bridge. Finally, because HTMLLoader is not supported on Android devices, as AIR developers working with HTML content on Android, we are stuck with StageWebView’s limitations. At least for AIR 2.5.</p> <p>At first glance, the situation thus seems a bit grim. There are a variety of reasons why AIR for Android does not currently support HTMLLoader, probably none of which I am at liberty to discuss here. But, suffice it to say that Adobe is working on improving the situation.</p> <p>And in the interim, all is not lost. For many use cases, StageWebView probably already suits most developers’ needs. And there are some things you can do with StageWebView that you simply cannot with HTMLLoader. For instance, because StageWebView employs the native Android WebKit under the hood, in most cases CSS 3 <code>@font-face</code> is supported out of the box (with TTF and OTF). This is something you currently don’t get with HTMLLoader on the desktop (which uses AIR’s own bundled WebKit).</p> <p>Finally, albeit the fact that bi-directional ActionScript/JavaScript communication is difficult, it is not impossible. This is a useful feature that may be non-obvious to some developers (it was to me!) so I will document it here:</p> <h3>ActionScript to JavaScript</h3> <p>ActionScript to JavaScript communication is fairly straightforward. Simply use the “javascript:” protocol. For instance:</p> <div class="highlight"><pre><code class="as3"><span class="n">swv</span><span class="o">.</span><span class="na">loadURL</span><span class="o">(</span><span class="s2">&quot;javascript:myJSFunctionName()&quot;</span><span class="o">);</span> </code></pre> </div> <p>This will invoke the function <code>myJSFunctionName</code> on the JavaScript side, assuming that the function exists and the page is fully loaded. If the function does not exist, no error will be thrown so use with care.</p> <p>One of the more interesting side-effects of the “javascript:” protocol is that you can also use it to perform JavaScript injection on any web content displayed in the StageWebView. For instance, to inject a new function called <code>myFunction</code> into a loaded page:</p> <div class="highlight"><pre><code class="as3"><span class="n">swv</span><span class="o">.</span><span class="na">loadURL</span><span class="o">(</span><span class="s2">&quot;javascript:var myFunction=&quot;</span> <span class="o">+</span> <span class="s2">&quot;function(){alert(&#39;Hello world!&#39;);}&quot;</span><span class="o">);</span> </code></pre> </div> <h3>JavaScript to ActionScript</h3> <p>JavaScript to ActionScript communication requires a bit more hacking. Presently, the best means of passing data from JavaScript to ActionScript is through encoded strings in the StageWebView’s location. Using JavaScript to set <code>document.location</code> will cause the StageWebView to dispatch a <code>LocationChangeEvent.LOCATION_CHANGING</code>. From here, we can use preventDefault() on the event to prevent the location from actually changing, while still extracting the data from the location. I typically use JSON as the data format, and make use of <a href="http://github.com/mikechambers/as3corelib">as3corelib</a>‘s JSON deserialization methods to handle the data on the ActionScript side. For instance, to get the HTML content width and height inside a StageWebView instance, on the JavaScript side you can use:</p> <div class="highlight"><pre><code class="js"><span class="nb">document</span><span class="p">.</span><span class="nx">location</span><span class="o">=</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span> <span class="p">{</span><span class="nx">width</span><span class="o">:</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">scrollWidth</span><span class="p">,</span> <span class="nx">height</span><span class="o">:</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">scrollHeight</span><span class="p">});</span> </code></pre> </div> <p>And on the ActionScript side:</p> <div class="highlight"><pre><code class="as3"><span class="n">swv</span><span class="o">.</span><span class="na">addEventListener</span><span class="o">(</span> <span class="n">LocationChangeEvent</span><span class="o">.</span><span class="na">LOCATION_CHANGING</span><span class="o">,</span> <span class="n">handleLocationChanging</span> <span class="o">);</span> <span class="kd">function </span><span class="nf">handleLocationChanging</span><span class="o">(</span> <span class="n">event</span><span class="o">:</span><span class="kt">LocationChangeEvent</span> <span class="o">):</span><span class="kt">void</span> <span class="o">{</span> <span class="n">event</span><span class="o">.</span><span class="na">preventDefault</span><span class="o">();</span> <span class="kd">var</span> <span class="n">data</span><span class="p">:</span><span class="kt">Object</span> <span class="o">=</span> <span class="n">JSON</span><span class="o">.</span><span class="na">decode</span><span class="o">(</span> <span class="n">event</span><span class="o">.</span><span class="na">location</span> <span class="o">);</span> <span class="nf">trace</span><span class="o">(</span> <span class="s2">&quot;Width: &quot;</span> <span class="o">+</span> <span class="n">data</span><span class="o">.</span><span class="na">width</span> <span class="o">+</span> <span class="s2">&quot;, Height: &quot;</span> <span class="o">+</span> <span class="n">data</span><span class="o">.</span><span class="na">height</span> <span class="o">);</span> <span class="o">}</span> </code></pre> </div> <h3>Debugging</h3> <p>Finally, it may be useful to know that any calls to <code>console.log()</code> in JavaScript in a StageWebView instance will show up in the Android debugger through “adb logcat”.</p> <p>And that’s it! Hopefully this will help a few developers who are getting started with AIR for Android and need to work with advanced HTML content.</p>
id http://sean.voisen.org/blog/2010/10/making-the-most-of-stagewebview
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2010/10/making-the-most-of-stagewebview
title
Stomach Contents: Structure - struct
value Making the most of StageWebView
updated 2010-10-29T07:00:00Z
13
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>One of the more notable problems with digital artifacts, besides their ephemeral and intangible nature, is that they tend to lack character. They are produced by machines and they are readily reproducible by other machines without marginal additional effort. They lack the individuality and imperfection that comes from something that was manufactured not as we come to think of it now, but in the original sense of the word — to be made (factured) by hand. Even as something as simple as a handwritten note on a scrap piece of paper has more character than anything made by machine.</p> <p>At the <a href="http://www.empsfm.org/">Experience Music Project</a> in Seattle, there is a <a href="http://en.wikipedia.org/wiki/Jimi_Hendrix">Jimi Hendrix</a> exhibit. And in this exhibit there are large posters of the lyrics to a few of Hendrix’s songs, blown-up photographs of scrawled handwritten notes Hendrix made on spare bits of hotel stationery from wherever he happened to be staying at the time. To see the lyrics, in Hendrix’s own handwriting, on stationery that places that single creative moment in both in geographical and chronological space … well that’s something that could just never happen if Hendrix had typed those same lyrics into the notepad application on his laptop computer. All the preserved emotion and individuality and character and authenticity of the scrawling Hendrix handwriting would have been lost. The creases in the paper, the subtle stains of age and even the contextual markers of the stationery logo and address — those would’ve been lost as well. In fact, a great deal of the visceral emotional power of the entire exhibit would have been completely and utterly … absent.</p> <p>One could ask: What would Jimi Hendrix have become had he been born in the 1992 instead of 1942? How would his music have changed if aided by digital tools? These are, however, meaningless questions. People are creations of their environments, and Hendrix was who he was because of when he was.</p> <p>A more appropriate question may be: How does creativity change when more and more of it is facilitated by machine? What happens when something as simple as song lyrics are typed out and stored in a digital file instead of handwritten on a physical sheet of paper? When the emotion conveyed by the irregular strokes of a pen is replaced by the uniform neatness of the Helvetica font, what changes? The answer can only be: everything.</p> <p>In the realm of creative expression one thing is apparent: Tools are tools, and all of them have inherent limitations, even machines. The personal computer is limiting not only because of its regimented, digital nature, but also because of its sedentary interaction pattern. Humans beings are embodied creatures, and sedentism is rarely conducive to creativity. Creativity comes not just from the mind acting through the fingers, but from the whole being. And creativity should be preserved in media that maintains the full fidelity of what that embodied experience is all about. Or — at the very least — more of that fidelity.</p> <p>Note: The irony that all of this is being published in digital is not lost on me.</p>
id http://sean.voisen.org/blog/2008/09/forget-about-digital-heirlooms
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2008/09/forget-about-digital-heirlooms
title
Stomach Contents: Structure - struct
value Forget about digital heirlooms
updated 2008-09-05T07:00:00Z
14
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>Taken from Professor Simon Penny’s <a href="http://ace.uci.edu/penny/wisdom/index.html">collection of sundry words of wisdom</a>. Somehow it feels appropriate today:</p> <blockquote><p>During the renovation of buildings for the ACE program, a man was sent to fix a problem with a door. When I encountered him he was enlarging a hole in a the door with a grinder so the lock would latch. I looked at the door and noted that that door was not latching because the screws holding the hinges to the door-frame had corroded and the door had dropped. I pointed this out to him, and suggested that he replace the screws in the hinges. He looked at me with pathetic incomprehension and said “I’m a lock guy, I’m not a door guy.” There is an appalling profundity in this response. It succinctly captures the kind of narrow thinking which ACE works against. In institutions of higher learning, emphasis is commonly placed on ‘problem solving’ as if problems were self-evidently lying about just waiting to be picked up. But in order to be solved, a problem must first be identified and framed. In the real world, problems seldom observe disciplinary borders. ‘Problem framing’ requires a kind of intellectual process which is diametrically opposed to ‘problem solving.’ It requires the ability to grapple with incongruities and incompatibilities and discontinuities. In my opinion, we are good at teaching the deductive processes of problem solving, but this only permits students to solve already framed ‘textbook’ problems. Self evidently, it is more important to ask the right question than to get the right answer. Except in isolated and informal pockets, we seem to be bad at teaching the process of asking the right question.</p></blockquote>
id http://sean.voisen.org/blog/2008/07/not-a-door-guy
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2008/07/not-a-door-guy
title
Stomach Contents: Structure - struct
value Not a door guy
updated 2008-07-26T07:00:00Z
15
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>Two facts: 1) Serendipity is the engine that powers the wonder of life and 2) when you read, life is often measured in periods demarcated by the dates before and the dates after the reading of a life-altering book.</p> <p>A life-altering book does not necessarily need to be a good book. It does not necessarily need to be a classic. In fact, informal surveys have shown me that it rarely is. Instead, the book simply needs to have the right message in the right format and arrive in the reader’s hands at exactly the right time. Hence, serendipity.</p> <p>The books I have read that have had a profound impact on my life — either emotionally, intellectually or spiritually — have never been chosen by me. They fell into my hands as random gifts or chance recommendations by friends, family members and even perfect strangers. Choosing your own books, either at the bookstore or at the library, even when the choosing is done in a purely whimsical manner, too often results in a closed feedback loop. You will always choose books on subjects that you know already appeal to you, written by authors with a style you know you will like. This echo-chamber intellectual silo is unavoidable without third-party support, and Amazon.com’s recommendation engine does not count as third-party support. It knows what you like and will just continue showing you books that fall within your core sphere of preference.</p> <p>What is needed is a serendipity engine. An engine for the engine, if you will. There are relatively low-tech versions of this. <a href="http://www.bookcrossing.com/">Bookcrossing</a> being one example. And a good one at that. The best solutions will, of course, be completely unpredictable, both in content and timing. A program that knows your personal zeitgeist and then, at entirely random intervals, hands you something entirely outside the realm of said zeitgeist. In this sense, a monthly book club recommendation does not work. The book should fall into your hands when you least expect it at a time when you probably don’t want to read it. But then you read it anyway.</p> <p><a href="http://www.amazon.com/Razors-Edge-W-Somerset-Maugham/dp/1400034205%3FSubscriptionId%3D1N9AHEAQ2F6SVD97BE02%26tag%3Deatorange-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1400034205">The Razor’s Edge</a> was like this. So was <a href="http://www.amazon.com/Ishmael-Adventure-Spirit-Daniel-Quinn/dp/0553375407%3FSubscriptionId%3D1N9AHEAQ2F6SVD97BE02%26tag%3Deatorange-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0553375407">Ishmael</a>, <a href="http://www.amazon.com/Fahrenheit-451-Ray-Bradbury/dp/0345342968%3FSubscriptionId%3D1N9AHEAQ2F6SVD97BE02%26tag%3Deatorange-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0345342968">Fahrenheit 451</a>, <a href="http://www.amazon.com/Zen-Art-Motorcycle-Maintenance-Inquiry/dp/0060589469%3FSubscriptionId%3D1N9AHEAQ2F6SVD97BE02%26tag%3Deatorange-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0060589469">Zen and the Art of Motorcycle Maintenance</a>, and Randy Pausch’s <a href="http://www.amazon.com/Last-Lecture-Randy-Pausch/dp/1401323251%3FSubscriptionId%3D1N9AHEAQ2F6SVD97BE02%26tag%3Deatorange-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1401323251">The Last Lecture</a>. In hindsight, it is obvious that there is certainly a common thread among all these books. Finding that thread is left as an exercise to the reader.</p>
id http://sean.voisen.org/blog/2008/07/reading-outside-the-feedback-loop
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2008/07/reading-outside-the-feedback-loop
title
Stomach Contents: Structure - struct
value Reading outside the feedback loop
updated 2008-07-20T07:00:00Z
16
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>What would an Internet without language feel like?</p> <p>In 1996 Dr. Jill Bolte Taylor <a href="http://www.ted.com/index.php/talks/jill_bolte_taylor_s_powerful_stroke_of_insight.html">suffered a stroke</a> that temporarily eradicated nearly all of the mental functions that were controlled by the left hemisphere of her brain — deductive reasoning, language, pattern and symbol recognition, recognition of self, &amp;c. Living for several weeks in a world without language, in a world without the ability to name or label things or judge things or give a damn about the details of life, she describes here experience as a Buddhist might describe a perpetual state of <a href="http://en.wikipedia.org/wiki/Samadhi">samadhi</a> — pure and effortless bliss. Apparently — or one might jump to the conclusion — the key to Nirvana lies in the right-half of the brain.</p> <p><a href="http://www.amazon.com/Whole-New-Mind-Right-Brainers-Future/dp/1594481717%3FSubscriptionId%3D1N9AHEAQ2F6SVD97BE02%26tag%3Deatorange-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1594481717">Dan Pink thinks</a> we live in a left-brain dominated world. He’s probably right. Or left. Never in its relatively brief history has the human species been so inundated language. From the Internet, to radio, to television, to iPods, to roadside billboards, to telephones, to text messages, to ads plastered on the sides of city buses, it is impossible to escape words. Nobody in the civilized world enjoys even the briefest luxury of linguistic silence. Rising stress levels and a complete lack of ability to focus (continuous partial attention, per chance) are just a few of the more prevalent results.</p> <p>The Internet is perhaps one of the biggest culprits of the crime of language overload. But what if it could be amended with some type of linguistic filter? A silent web devoid of words, both written and spoken alike. An Internet of images, photos, video and instrumental music only. Google searches made possible only by uploading an image or photograph and finding similar results. How would the experience be different? How would the left hemisphere revolt? What would the whole thing feel like?</p> <p>Gorging ourselves on a never-ending smörgåsbord of words, it’s sometimes easy to forget that the world is made of more than just mental constructions, and that a great deal of communication takes place outside the narrow bandwidth of language alone.</p>
id http://sean.voisen.org/blog/2008/07/muting-the-web
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2008/07/muting-the-web
title
Stomach Contents: Structure - struct
value Muting the web
updated 2008-07-07T07:00:00Z
17
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>There is a hypothesis that says that the purpose of sleep is to reinforce certain memories, or rather, neural connections, that were created during the previous day. Sleep does this not in a way that one might expect &mdash; by actually strengthening the connections &mdash; but rather by subtly washing away the neural connections created during the day that are deemed trivial or unimportant. Leaving only the most important ones remaining. A bit like waves washing gently on a rocky beach over thousands of years &mdash; eventually most of the rocks are turned to sand and only the largest rocks remain.</p> <p>When it comes to the preservation of culture, time, I think, works quite similarly. Take literature, for instance. Of the many millions of bodies of text that have been created over the thousands of years since man first invented writing, only a very few have been continually preserved and set aside as &ldquo;classics.&rdquo; The rest were beaten into sand and washed away by the ocean of time.</p> <p>This isn&rsquo; a random process either. The Iliad or the Old Testament or Beowulf or Hamlet aren&rsquo;t available to us today by mere fortunate happenstance. Society made great efforts to keep them in circulation and preserve them. If culture is like a brain distributed across a certain population, and time is its sleep, then these cultural works are the synapses that matter. Somehow. Even though when you read them in high school it doesn&rsquo; seem that way.</p> <p>Will the Internet and digital storage media do away with this form of cultural sleep? If everything can be preserved, whether or not it is of significant cultural value, will it? Where then will classics come from? Or will culture break down into nervous chaos &mdash; where everything is of equal importance and so nothing is of importance at all &mdash; perhaps like the mind of a chronic insomniac?</p> <p>Even in a digital world, preservation of information still requires time, money and resources, albeit small. Websites come and go. So do blogs. They are more ephemeral even than books. So, perhaps the reverse will be the case &mdash; that because we can preserve anything, we don&rsquo;t produce anything worth preserving, and thus preserve nothing at all. Either way, in the future, the mechanisms by which culture evolves will almost surely be different.</p>
id http://sean.voisen.org/blog/2008/06/the-internet-cannot-be-curated
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2008/06/the-internet-cannot-be-curated
title
Stomach Contents: Structure - struct
value The internet cannot be curated
updated 2008-06-28T07:00:00Z
18
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>From Thoreau’s Walden (p. 12 of the Barnes and Noble edition):</p> <blockquote><p>One farmer says to me, “You cannot live on vegetable food solely, for it furnishes nothing to make bones with;” and so he religiously devotes a part of his day to supplying his system with the raw material of bones; walking all the while he talks behind his oxen, which, with vegetable-made bones, jerk him and his lumbering plough along in spite of every obstacle.</p></blockquote> <p>Michael Pollan’s In Defense of Food would have us believe that despite the nearly 200 years of scientific advances since this passage was written, we’re just as confused about nutrition as we always were, if not more so. He’s probably right.</p>
id http://sean.voisen.org/blog/2008/05/vegetable-made-bones
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2008/05/vegetable-made-bones
title
Stomach Contents: Structure - struct
value Vegetable-made bones
updated 2008-05-28T07:00:00Z
19
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>Did I mention that I am going back to school? No, I don’t think I did.</p> <p>About a month ago I found out that I was officially accepted to the <a href="http://ace.uci.edu">Arts Computation Engineering (ACE)</a> program at the <a href="http://www.uci.edu">University of California, Irvine</a>. Technically, I will be working on a master’s degree in information and computer science, but given that I will be a part of the ACE program, that strict designation is perhaps a bit misleading.</p> <p>Most of the time, graduate studies center on specialization — choosing a field of study and becoming a specialized expert in that field. But ACE doesn’t fit that mold. A blend of art, computer science, electronics, cultural studies, HCI and cognitive science, ACE is designed for the unabashed generalist. The closest comparable program I can think of is the Interactive Telecommunications Program at NYU. Before applying to ACE, I actually looked into ITP, but the daunting prospect of moving to the other side of the country to live in the nation’s most expensive city (Manhattan) to attend an equally expensive school just didn’t make economic sense to me. Albeit its relative closeness to my hometown of San Diego, and its greater affordability (UC Irvine is a state school), ACE just seemed the better choice. It’s smaller, more intimate, and headed by some top-notch professors. (The most recognizable name to any reader of this blog would probably be <a href="http://en.wikipedia.org/wiki/Paul_Dourish">Paul Dourish</a>, a former researcher with Xerox EuroPARC.)</p> <p>Why go back to school? It’s an important question to consider. In my field I certainly won’t make any more money with an advanced degree. I work as an independent contractor, and with the exception of a brief nine months as a full-time employee at a software company in Denver, I’ve essentially run my own businesses since high school. Career advancement through degrees doesn’t ever cross my mind. But I’m not in it for the degree, per se. I’m in it for the education and the opportunity.</p> <p>Creating software for desktop and web-based computing is fun and challenging, but also has an inherent limitation for potential. The future of computing lies not on the desktop, but in ubiquitous computing, ambient systems, mobile devices and the like. The current computational paradigm, I believe, has transformed an entire generation of human beings into sedentary and disembodied minds that must interact with their machines — and by extension, other people — solely through the mouse and keyboard. It’s served us well in many respects, but has limited us in a myriad others. And, thankfully, something better is on the horizon. I want to research, build and discover that “something better.”</p> <p>A life of researching, teaching and tinkering is something I feel I’m particularly well-suited for, as I’ve always been a bit of an academic and a hacker. The bureaucracy, hierarchy and egotism of academic life have been the only things keeping me away from going back to school thus far, primarily because I value my freedom of time above all else. We’ll see how it goes come September.</p> <p>As for research interests, I can only describe them in the broadest sense: toys and informatics. I’m extremely interested in mining the vast amounts of raw data now available at our fingertips, and finding patterns — looking for pertinent and <strong>actionable</strong> localized information that can be made available to people as integrated facets of their environment. And as potentially pragmatic as that sounds, I’m also equally interested in what I’ll just call “whimsical devices” — toys and devices that inspire some sense of wonder, or connect the user to their environment or other people in unique and inspiring ways. One of the best examples to illustrate what I’m talking about here may be <a href="http://en.wikipedia.org/wiki/Tod_Machover">Tod Machover’s</a> <a href="http://www.toysymphony.net/">Toy Symphony</a> project.</p> <p>So, come September it’s back to school for me. With much more of my time spent reading, researching and exploring new ideas, hopefully this will also translate into more blogging in the coming months. The frequency of posting has been scant these days. No promises though.</p>
id http://sean.voisen.org/blog/2008/04/back-to-school
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2008/04/back-to-school
title
Stomach Contents: Structure - struct
value Back to school
updated 2008-04-17T07:00:00Z
20
Stomach Contents: Structure - struct
content
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
type html
value <p>This is a blog post long overdue.</p> <p>My notes from the last two days at ETech are sparse. This is partially because of my own growing laziness during the latter days of the conference, and partially because I (like to think) I was making a concerted effort to spend more time listening and absorbing, and less time trying to capture it all. Though note-taking certainly improves retention, its distractions can also lead to a lot of missed visual and auditory intake.</p> <p>ETech is a hacker’s conference. It is a conference for technologists and programmers and designers and people who spend their days making things. At least, it certainly felt that way. The number of sessions with titles containing words like “hacks” or “hacking” or “do-it-yourself” seemed to far outweigh those that did not. But perhaps that’s just biased retrospection. On the first day, Tim O’Reilly delivered a rousing keynote that essentially boiled down to a 30-minute praise of hackers and makers and geeks in the trenches. My sense was that about half the people there were actually hackers, and the other half were people just trying to keep tabs on what the hacker/technologist community is up to.</p> <p>Now, technology for technology’s sake is all well and good, but it’s not my primary interest, and I was happy to find that there were several presenters at the conference attempting to push the hackers to create technology for social good. “Green” technology was a big theme this year. Saul Griffith delivered a massively in-depth keynote on calculating personal energy consumption, the contents of which can now be found at <a href="http://wattzon.org">wattzon.org</a>. Even more rousing, however, was <a href="http://www.lessig.org/">Larry Lessig’s</a> special evening keynote on government corruption — an impassioned plea for hackers to start using technology to help expose what’s really going on in Washington. The <a href="http://www.sunlightfoundation.com/">Sunlight Foundation</a> is a good first step in the right direction. Also, if you’ve never seen Lessig deliver a Powerpoint presentation, you should — it’s a brilliant example of how to turn the typical idiocy of Powerpoint on its head.</p> <p>It was a lot to assimilate in a mere four days, and I was mentally exhausted by the end of it all. This was a conference jam-packed with a lot of smart people; some with egos to match their IQs, and others far more humble. I walked away with more project ideas than I could feasibly implement, and a larger network of people who know how to make some of those ideas a reality.</p> <p>Was it worth it? For some, ETech can be prohibitively expensive. But if you really want to know where the next wave of technology is heading, and you pay attention and talk to enough people at the conference, it is possible to justify the cost. For me, it was just nice to have so many inspiring conversations with so many smart and like-minded people. Also, it doesn’t hurt to note that events like this are never without their unexpected surprises. Case in point: I spent my last few minutes at ETech learning how to pick locks during an impromptu lock-picking session delivered by a local San Diego hacker (and self-described “random douchebag”) — something that was definitely not on the official schedule. The maxim holds true again: the true value of any conference lies not in the speeches and sessions, but in the chance encounters and random hallway conversations with people you’ve never met before.</p>
id http://sean.voisen.org/blog/2008/03/the-belated-etech-wrap-up
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/blog/2008/03/the-belated-etech-wrap-up
title
Stomach Contents: Structure - struct
value The belated ETech wrap-up
updated 2008-03-22T07:00:00Z
id http://sean.voisen.org/
link
Stomach Contents: Structure - array
1
Stomach Contents: Structure - struct
href http://sean.voisen.org/
rel alternate
type text
2
Stomach Contents: Structure - struct
href http://feeds.feedburner.com/voisen
rel self
type application/atom+xml
3
Stomach Contents: Structure - struct
href http://pubsubhubbub.appspot.com/
rel hub
4
Stomach Contents: Structure - struct
href http://creativecommons.org/licenses/by-sa/2.0/
rel license
type text/html
rights Copyright (C) 2005-2011 Sean Voisen
title
Stomach Contents: Structure - struct
type text
value Sean Voisen
updated 2013-04-16T07:01:56Z
version atom_1.0

Sean Voisen

Developer at Adobe XD. Writer at The Kōan. I make software that helps people share and create. http://sean.voisen.org

@larz @aaronshekey @tfeener @najunghoya @nnnnic @dam @super_sonja @aaronshekey NEED MOAR TWITTER HANDLEZ. Be there with bells on.@svoisen

San Francisco, California