← Back to Envy Labs
caikesouza

Chaining scopes in Rails 4

Coming up in Rails 4 are big changes in ActiveRecord and how scopes work when chained together into a single query.

Up until Rails 3.x, chaining scopes that use the same column have followed the “last where wins” rule. This means that only the last condition involving that specific column is actually used in the query.

# in Rails 3
class User < ActiveRecord::Base
  scope :active,   -> { where(state: 'active') }
  scope :inactive, -> { where(state: 'inactive') }
end

User.active.inactive
# => SELECT * FROM users WHERE state = 'inactive'

Because both scopes are using the same state column, the query in the last used scope overrides the first one. This behavior is confusing and violates the Principle of Least Surprise.

image

Starting in Rails 4, sequential calls to scopes that share a common column between them will simply append the conditions using the AND statement, without dropping any previous conditions.

User.active.inactive
# => SELECT * FROM posts WHERE state = 'active' AND state = 'inactive'

This is now the same behavior as combining class methods which return scopes.

class User < ActiveRecord::Base
  def self.active
    where(state: 'active')
  end
  def self.inactive
    where(state: 'inactive')
  end
end

User.active.inactive
# => SELECT * FROM posts WHERE state = 'active' AND state = 'inactive'

It is now up to the programmer to opt-in to the “last where wins” logic by explicitly using the merge method.

User.active.merge(User.inactive)
# => SELECT * FROM users WHERE state = 'inactive'

Changes like these tend to be the cause for mysterious bugs that take forever to be found in applications that lack a decent test suite, so having strong test coverage is crucial for upgrading your application to Rails 4.

To see the complete list of changes in ActiveRecord, checkout the CHANGELOG

- Carlos Souza

06.07.13
mattschultz

A Look at Directives in AngularJS

AngularJS, the Superheroic JavaScript MVW Framework, simplifies many of the challenges associated with developing single-page web applications. AngularJS is a full-featured framework, but we are just going to look at its most conceptually unique feature: directives.

Directives are used to add new syntax and behavior to the DOM. Angular ships with its own set of directives, but also gives us the ability to create our own. Using directives, we can extract complex and repetitive parts of our user interface into easily reusable building blocks.

The ‘Preview’ Directive

In the following scenario, we have a page that lists posts. We don’t want to show the entirety of the post, so we truncate it. Hovering over the text reveals the rest of the post. That code might look something like this:

<div class="post truncate">
There's still plenty of meat on that bone. Now you take this home, throw it in a pot, add some broth, a potato. Baby, you've got a stew going.
</div>
$(function() {
$('.post').bind('mouseenter mouseleave', function() {
$(this).toggleClass('truncate');
});
});

JSFiddle

Wouldn’t it be nice if we could simply do the following?

<preview>There's still plenty of meat on that bone. Now you take this home, throw it in a pot, add some broth, a potato. Baby, you've got a stew going.</preview>

Here’s what that implementation looks like as a directive:

var myApp = angular.module('myApp', []);

myApp.directive('preview', function () {
return {
restrict: 'E',
template: '<div ng-class="{ truncate: isTruncated }" ng-transclude></div>',
scope: {},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.isTruncated = true;
element.bind('mouseenter mouseleave', function() {
scope.isTruncated = !scope.isTruncated;
scope.$apply();
});
}
};
});

JSFiddle

Let’s break that down piece by piece:

var myApp = angular.module('myApp', []);

myApp.directive('preview', function () {
return {

}
});

Here, we declare a directive called preview on our Angular module and return a directive definition object. In this example, that directive definition object defines the restrict, template, scope, replace, transclude, and link properties.

restrict: 'E'

This says our directive can only be invoked as an element:

<preview>...</preview>

What if we preferred not to use custom HTML elements? Fortunately, Angular gives us several options. We could, for example, change that E to an A (for attribute) and invoke our directive like so:

<div preview>...</div>

We could also combine these letters (e.g. EA) to allow the directive to be invoked either way.

template: '<div ng-class="{ truncate: isTruncated }" ng-transclude></div>'

This is the HTML our directive generates.

ng-class is a built-in Angular directive that applies a class to the element based on the result of an expression. In this case, we’re applying the truncate class whenever isTruncated evaluates to true.

We’ll talk about that ng-transclude attribute in a bit.

scope: {}

This creates an isolate scope. We do this so the isTruncated value is unique to each instance of our preview directive. Otherwise, hovering one preview element would reveal the content in all of them.

To learn more about the isolate scope, check out this Egghead screencast.

replace: true

This tells the directive to replace the invoking element with the HTML in the template. If set to false, the directive would append the `template` to the invoking element, rather than replacing it.

transclude: true

transclude makes the innerHTML of the invoking element available to use within our directive. Using the included ng-transclude directive, we can insert that HTML into our template:

template: '<div ng-class="{ truncate: isTruncated }" ng-transclude></div>'
link: function(scope, element, attrs) {
    scope.isTruncated = true;
    element.bind('mouseenter mouseleave', function() {
        scope.isTruncated = !scope.isTruncated;
        scope.$apply();
    });
}

link is where we define our directive’s custom behaviors. Event listeners and code that updates the DOM both go here.

Best Practices and Final Words

Creating directives allows us to successfully encapsulate markup and behavior in a way that is easily reusable. While the previous example was rather simple, the utility of directives increases as your application grows and its markup and behavior become more complex.

If you find yourself repeating chunks of HTML throughout your app, you should extract it into a directive. If you’re performing any DOM manipulation in your controllers, that code is better suited in a directive (it’s also a commonly agreed upon best practice). When used properly, directives simplify your HTML and serve as reusable building blocks for your application.

Resources

The preview directive code can be found on JSFiddle. To see some other real-world examples, I recommend checking out the directives in the AngularUI project.

If you’re just getting started with AngularJS, Code School subscribers can check out my Code TV screencasts, then dive deeper into more specific topics at John Lindquist’s Egghead.

- Matt Schultz

06.04.13
caikesouza

Understanding Node.js

Node.js is a framework for writing server-side JavaScript applications. It is built on top of the V8 JavaScript runtime and uses an event-driven, non-blocking I/O model that makes it perfect for data-intensive, real-time applications.

This blog post will describe what non-blocking I/O means and how working with the event loop can help your applications be more efficient.

“This [non-blocking I/O] model simplifies access to slow resources in a scalable way that is intuitive to JavaScript programmers and easy to learn for everyone else.” - Node Up and Running.

The Restaurant

In order to understand non-blocking I/O, let’s picture a common scenario. Suppose you are at a restaurant with friends. A typical experience at a restaurant would be something like this:

  1. You sit at a table and the server grabs your drink order.
  2. The server goes back to the bar and passes your order to a bartender.
  3. While the bartender is working on your drink, the server moves on to grab another table’s drink order.
  4. The server goes back to the bar and passes along the other table’s order.
  5. Before the server brings back your drinks, you order some food.
  6. Server passes your food order to the kitchen.
  7. Your drinks are ready now, so the server picks them up and brings them back to your table.
  8. The other table’s drinks are ready, so the server picks them up and takes them to the other table.
  9. Finally your food is ready, so server picks it up and brings it back to your table.

A restaurant server taking ordersA Restaurant server taking orders

Basically every interaction with the server follows the same pattern. First, you order something. Then, the server goes on to process your order and return it to you when it’s ready.

Once the order is handed off to the bar or kitchen, the server is free to get new orders or to deliver previous orders that are completed. Notice that at no point in time is the server doing more than one thing. They can only process one request at a time.

This is pretty much how non-blocking Node.js applications work. In Node, your application code is like a restaurant server processing orders, and the bar/kitchen is the operating system handling your I/O calls.

I/O callsI/O Calls

Your single-threaded JavaScript application is responsible for all the processing up to the moment it requires I/O. Then, it hands the work off to the operating system which takes care of processing the rest.

What is I/O ?

Once an application has started, it is loaded into the machine’s memory. That’s what the CPU will mostly use for running your program. I/O is shorthand for Input and Output and it means accessing anything outside of your application.

Accessing memory is pretty fast, hence a lot of caching mechanisms simply use RAM to store data. However, applications will often need to access the network or read from a text file, and these types of I/O are by far the slowest types. That’s where non-blocking I/O really shines.

Blocking I/O

Back to our restaurant example, if every time the server got an order request they had to wait for the bar/kitchen to finish before taking the next request, then the service for this restaurant would be very slow and customers would most likely be unsatisfied. This is how blocking I/O works.

Consider the following code example:

// requesting drinks for table 1 and waiting...
var drinksForTable1 = requestDrinksBlocking(['Coke', 'Iced Tea', 'Water']);
// once drinks are ready, then server takes order back to table.
serveOrder(drinksForTable1);
// once order is delivered, server moves on to another table.

// requesting drinks for table 2 and waiting...
var drinksForTable2 = requestDrinksBlocking(['Beer', 'Whiskey', 'Vodka']);
// once drinks are ready, then server takes order back to table.
serveOrder(drinksForTable2);
// once order is delivered, server moves on to another table.

// requesting food for table 1 and waiting..
var foodForTable1 = requestFoodBlocking(['Hamburger', 'Salad', 'Pizza']);
// once food is ready, then server takes order back to table.
serveOrder(foodForTable1);
// once order is delivered, server moves on to another table.

In the previous example, both the requestDrinksBlocking and requestFoodBlocking functions perform some sort of blocking I/O call, and the whole process stops while it waits for the I/O operation to finish. Good thing this isn’t how most restaurants operate!

Non-Blocking I/O

Our previous example re-written for a non-blocking I/O model allows for multiple I/O calls to be performed without halting the execution of the program. Instead, these calls run independently.

// requesting drinks for table 1 and moving on...
requestDrinksNonBlocking(['Coke', 'Iced Tea', 'Water'], function(drinks){
  return serveOrder(drinks);
});

// requesting drinks for table 2 and moving on...
requestDrinksNonBlocking(['Beer', 'Whiskey', 'Vodka'], function(drinks){
  return serveOrder(drinks);
});

// requesting food for table 1 and moving on...
requestFoodNonBlocking(['Hamburger', 'Salad', 'Pizza'], function(food){
  return serveOrder(food);
});

The callback functions passed as arguments are invoked asynchronously when the return value from their respective I/O calls are available. This looks like a much better restaurant to go to!

The Event Loop

Now that we’ve seen how to write non-blocking Node.js code, let’s take a look at the missing piece of the puzzle. This is the part responsible for actually invoking the callbacks: the event loop.

When non-blocking I/O calls are complete and their return value is available, they emit an event.

Node’s approach to handling these events leverages a well known feature in JavaScript: functions as first class citizens. As we’ve seen in our previous example, we simply pass functions as callback arguments to Node’s non-blocking functions. These callbacks are invoked when the return value from their current I/O calls are available and the proper events are emitted.

Suppose there is a ready event that is emitted when an order is ready. Another way to write the previous code would be to explicitly listen to the ready event:

// requesting drinks for table 1 and listening to the 'ready' event.
var requestDrinksTable1 = requestDrinksNonBlocking(['Coke', 'Iced Tea', 'Water']);
requestDrinksTable1.on('ready', function(drinks){
  return serveOrder(drinks);
});

// requesting drinks for table 2 and listening to the 'ready' event.
var requestDrinksTable2 = requestDrinksNonBlocking(['Beer', 'Whiskey', 'Vodka']);
requestDrinksTable2.on('ready', function(drinks){
  return serveOrder(drinks);
});

// requesting food for table 1 and listening to the 'ready' event.
var requestFoodTable1 = requestFoodNonBlocking(['Hamburger', 'Salad', 'Pizza']);
requestFoodTable1.on('ready', function(food){
  return serveOrder(food);
});

In Node, all objects that listen to or emit events, inherit from EventEmitter.

Blocking the Event Loop

Applications written in Node run on a single-thread. This means that they can only do one thing at a time, just like our restaurant server.

Let’s say that when your food order is ready, the server needs to count the total number of beans in your lentil soup:

requestFoodNonBlocking('Lentil Soup', function(soup){
  countNumberOfBeans(soup); //blocks...
  return serveOrder(soup);
});

The server is able to pass along your food order to the kitchen in a non-blocking fashion and then proceed to do other things. However, once your order is back, they start to count the number of beans in your soup and simply block. They won’t be able to do anything else until they are done counting the beans.

If for some reason countNumberOfBeans(soup) results in an infinite loop, then the server is stuck there forever and you will be forced to look for food somewhere else.

Conclusion

Writing server-side JavaScript in Node.js is easy and fun. It doesn’t take much to get up to speed and start writing efficient, non-blocking applications that can handle heavy traffic.

Being single-threaded means that Node.js programs can only do one thing at a time, so it is important to understand how to properly work with the event loop in order to take full advantage of the platform and avoid common pitfalls. For applications that require heavy computation and not much I/O, Node might not be your best choice.

If you want to learn more about Node.js, be sure to check out the Real-time Web with Node.js course over at Code School.

Also, Jacob Swanner and I will be teaching a Node.js workshop next week at O’Reilly Fluent Conference in San Francisco. Come and say hi if you are there!

- Carlos Souza

05.16.13
greggpollack

Announcing Starter Studio

Here at Envy Labs we love helping build our local tech community here in Orlando.  Today we’re happy to announce yet another big initiative of ours, the Starter Studio.  The Starter Studio is a 3 month program for startups which combines educational programming with mentorship to help them succeed.  Our first class is now open for applications, and we’re targeting EdTech Startups.  

See the video we threw together below for more information.  =)

05.15.13
caikesouza

RailsConf 2013

RailsConf 2013

The Envy Labs and Code School team just got back from RailsConf 2013 in beautiful Portland, OR. The conference was very well organized by the folks at Ruby Central and it was a great chance to meet fellow Ruby on Rails developers from other parts of the globe.

This year the conference was composed of four days of talks, split up into multiple tracks. One of them was exclusively devoted to beginner level topics, focused on newcomers to the Rails framework. Aimee Simone and Christopher Green talked about How a Request becomes a Response and presented our Rails For Zombies 2 course.

image

It’s always great to see new people interested in learning Rails!

One the second day, Thomas Meeks shared his thoughts on project documentation and testing, with the very appropriately titled presentation Delicious Controversy: Docs & Tests. I must confess I was a little skeptical the first time I saw Thomas presenting this talk in our office, but after seeing it for the third time now his arguments are starting to make sense.

image

Thomas points out that practicing Test-driven Development doesn’t guarantee good application design and, more often than not, Rails developers tend to overtest their apps. He basically argues for more coarse grained tests using Service Objects. I definitely recommend checking out Thomas’ slides and watching the video for his talk once it’s available.

After the keynote on the third day of the conference, Gregg Pollack presented the Ruby Hero Awards. This award is given to a select group of amazing contributors and unsung heroes who spent the last year producing educational content, developing plugins and gems, contributing to open-source projects, or putting on events to help developers learn and grow.

image

This year’s winners are Terence Lee, Sandi Metz, Mike Perham, James Tucker, Brian Shirai, and the Rails Girls team: Linda Liukas, Pia Henrietta K and Karri Saarinen. Many thanks to the Heroes for their hard work!

Last time our team was in Portland, we found this really cool retro arcade place called Ground Kontrol, and realized it would be the perfect place to hold a Code School party. So at the end of the third day of the conference, we rented out Ground Kontrol and invited all of our Code School students attending RailsConf for a night of retro gaming and a lot of fun!

Between rounds of Pac-Man Battle Royale, Street Fighter II and other classics, we were able to learn a little bit more about the people that take our courses.  

image

This was invaluable feedback, and a reassurance that Code School is helping people achieve their life goals and find a job that makes them happy.

Aside from the conference, we also had the chance to walk around Portland, check out some restaurants and coffee shops, and visit some places outside the city as well. Some of our team drove up to the famous Mount Hood, where we planted the Envy Labs flag near the top.

image

Seriously, look for our flag next time you are there.

We are all back home now, super excited to start researching and trying out all of the cool things we learned this past week.

Looking forward to RailsConf 2014 in Chicago!

- Carlos Souza

05.06.13
caikesouza

Rails 4 removes whiny_nil

One of the many changes coming up in Rails 4 is the removal of whiny_nils. This feature was responsible for displaying a friendly message when calling id on a nil object. In this post, we’ll look at why this feature was added back in version 1 and the reason it’s been removed in Rails 4.

image

Ruby 1.8.7

Back in Ruby 1.8.7, calling NilClass#id would return the number 4:

nil.id # => 4

This is because all objects in Ruby have an internal identifier, returned by the id method:

FALSE.id # => 0
0.id # => 1
TRUE.id # => 2

Starting in Ruby 1.9, the id method was replaced in favor of the new object_id method:

FALSE.object_id # => 0
0.object_id # => 1
TRUE.object_id # => 2
nil.object_id # => 4

So if we call nil.id on Ruby 1.9.x or higher versions, we get a NoMethodError:

0.id # => NoMethodError: undefined method `id' for 0:Fixnum

Rails 3 and whiny_nils

Suppose that we have the following code on a Rails 3 application, returning an empty collection:

@posts = Post.where(title: 'Rails 5')
@posts.length # => 0

If we assume the collection is not empty and decide to pick the first post, then we will end up calling id on nil:

@post = @posts.first
@post.class # => NilClass
@post.id # => RAILS RAISES ERROR!

We have just seen that NilClass#id actually exists in Ruby 1.8.7, which is supported by all major versions of Rails up to, and including, 3.x. However, since id is a fundamental method of ActiveRecord models, previous versions of Rails would intercept calls to NilClass#id, raising an error and displaying an informative warning instead of simply retuning the number 4:

Called id for nil, which would mistakenly be 4 — if you really
wanted the id of nil, use object_id

Rails assumed that we probably wanted a model database identifier (like a table primary key), and the number 4 returned by the original method could result in obscure bugs.

Rails 4

Rails 4 requires Ruby version 1.9.3 or higher. This means that whiny_nils are not needed anymore, since internal identifiers for Ruby objects are now exclusively returned by the object_id method.

@post = @posts.first
@post.class # => NilClass
@post.id # => NoMethodError
@post.object_id # => 4

Instead of the previous friendly message along with the error, Rails 4 simply raises a NoMethodError.

 @post.id # => NoMethodError: undefined method `id' for nil:NilClass

The removal of the whiny_nil feature is just one of the many changes coming up in Rails 4. To learn more about what’s new, check out our series of screencasts on Rails 4.

Need help migrating your existing Rails projects to Rails 4? We can help you!

- Carlos Souza

05.03.13
caikesouza

Rails 4 Routing Concerns

One of the new features in the upcoming Rails 4 release is called routing concerns. This feature helps reduce code duplication on your routes file by allowing you to declare common routes that can be reused inside other resources and routes.

image

Take the following set of routes, for example:

resources :messages do
  resources :comments
  resources :categories
  resources :tags
end
 
resources :posts do
  resources :comments
  resources :categories
  resources :tags
end
 
resources :items do
  resources :comments
  resources :categories
  resources :tags
end

Notice the duplication every time we want to state that a resource can have comments, categories and tags. Let’s extract these into a concern called sociable:

concern :sociable do
  resources :comments
  resources :categories
  resources :tags
end

We can now use the sociable concern to reference these set of resources:

resources :messages, concerns: :sociable
resources :posts, concerns: :sociable
resources :items, concerns: :sociable

Concern blocks can also take an options argument, which is passed down to the resources, like so:

concern :sociable do |options|
  resources :comments, options
  resources :categories, options
  resources :tags, options
end

resources :posts do
  concerns :sociable, only: :create
end

Routing concerns is a feature that helps keep our routes clean and easy to maintain. It will be part of Rails 4, but if you wish to use this feature in your Rails 3.2 applications, you can do so via the routing_concerns gem

- Caike Souza

(source: http://www.flickr.com/photos/teacherafael/886753421)

02.14.13
caikesouza

Rails 4 Security for Session Cookies

Rails 4 session cookies are now encrypted, and they use the EncryptedCookieStore class for storing session data. Encrypted cookie data is difficult to alter or even read by attackers.

Cookie Monster

Projects generated with Rails 3 use a different, digitally signed cookie as the default store for sessions. Those are also difficult to alter, but easier to read from. Aside from EncryptedCookieStore, Rails 4 also offers a type of cookie store to help you transition from digitally signed to encrypted cookies. It is called UpgradeSignatureToEncryptionCookieStore.

In order to use this undoubtedly descriptive cookie store, set session_store type to :upgrade_signature_to_encryption_cookie_store in your config/initializers/session_store.rb file.

Then, run rake secret from the terminal to generate a secure key. Using that secure key, add Myapp::Application.config.secret_key_base = <your_key> in your config/initializers/secret_token.rb, but do not remove the existing Myapp::Application.config.secret_token line.

By doing this, all previous digitally signed sessions will still be valid and will automatically be upgraded; new sessions will be created already with encryption.

If you happen to share your code publicly, make sure your secret_key_base value is kept private.

For more information on upgrading from Rails 3 digitally signed cookies to Rails 4 encrypted cookies, please check out the Rails Edge upgrade guides

UPDATE 2013-05-08: With the release of Rails 4.0.0.rc1, the upgrade_signature_to_encryption_cookie_store session_store type has been removed. Now, by simply setting values for both secret_key_base and secret_token, Rails will automatically upgrade existing signed cookie-based sessions to be encrypted.

- Caike Souza

(source: http://www.flickr.com/photos/nathaninsandiego/3757033518)

01.28.13
greggpollack

Ruby Developers Wanted

Update: The positions have been filled for now.  However, don’t let that stop you from applying!  There’s good odds we’ll need more within the next few months.  FYI, best way to stay on top of our needs is to hang out around us.  Come to Betas and the Ruby Users Group here in Orlando.

We’re looking for another mid to senior level Ruby developer for both Envy Labs and Code School.  For the Envy Labs side we’re looking for someone who enjoys working on lots of challenging client projects with our killer team of project managers and designers.  For the Code School side we’re looking for someone who is passionate about educational technology and teaching programming in the best way possible.  You’ll need to be able to work in the office here in Orlando.  

image

What we have to offer:

  1. Great office in the middle of downtown, with a beautiful view.
  2. Competitive Salary & Healthcare. 
  3. Equity after a year.
  4. A laid-back work environment.
  5. You get to work with a team that loves learning, and getting better at what we do.
  6. We’ll pay for you to go to one remote and one local conference a year.
  7. If you want to speak at tech conferences, we’ll help pay to get to more.
  8. If you’re a fan of video / audio production, we do lots of that and you can get involved.
  9. If you want to teach, lots of opportunities to get paid to create educational content.
  10. Rarely any overtime.  We have families and enjoy spending time with them.
  11. We’re deeply involved in the Orlando tech & startup community.  
  12. A great culture and work environment.  Here’s some perks:
  • Optionally work from home Tuesdays & Thursdays.
  • No set hours on M/W/F.  Wander in when you like.
  • Monthly company outings.
  • Whiskey Wednesdays / Two beers on tap for relaxing time.
  • Ping pong table.
  • Lots of local tech events in our space at night.
  • Catered lunch every Friday.
  • Paid betterment every other Friday afternoon.  This is where we put client work down and work on anything you like (as long as it makes you better).  
  • All the Espresso, Coffee, Tea, & Sodas you can drink.
  • Lots of free snacks.
  • Scheduled raises, so there’s no question when you’ll get your next bump.

I get a lot of happiness from providing for people and creating an awesome work environment.  I suspect this is because I had lots of shitty work experiences.  We’ve all been there.

If you think you might be a good fit for our team, please don’t hesitate to drop us a line a jobs@envylabs.com and let us know which position you’re interested in.  

Oh, and in case you’re wondering, here’s how to impress us:

  • Show us open source contributions.
  • Show us well tested code.
  • Show us technical writing (blog posts or documentation) you’ve done.
  • Show us conference talks you’ve done.
  • Tell us other technologies you’ve used (aside from Rails).. i.e. Backbone, CoffeeScript, NoSQL DBs, Ember.. and what you think of them etc.
  • On the Code School side: What’s your code school user profile URL?  What’s one way you think we could improve Code School.
  • On the Envy Labs side: Have you ever been a tech lead on a client project?  How do you try to facilitate communication with clients?  What’s your philosophy?
  • Are you good at ping pong?  

-Gregg Pollack

01.24.13
envylabs-blog

Rewriting Science Fiction

The lot of us self-proclaimed “nerds” in the tech environment can still feel experiential echoes of the moment Tom Cruise donned the “glove” to begin a tech-dance with the G-Speak Spatial Operating Environment in Spielberg’s Minority Report. It was the stuff dreams were made of—whizzing and whirling, manipulating a pulsing, breathing interface with tactile ferocity. John Underkoffler and his team gave legs to a ghost that previously only existed in thought and desire.

Science Fiction finally felt like Scientific History.

But film is one thing, and real life is another. Science Fiction has long been an advocate for progressing the discussion on design and interaction. In architecture, fashion, and technology, sci-fi has shaped our future by lending a hand with the building blocks of actualization. Yet the future we were promised seems all but nearby.

Multi-touch

With the announcement of the G-Speak technology at TED2010, this felt more tangible than ever. Following hot in pursuit was the Xbox Kinect, leveraging a similar interactive architecture to allow manipulation of the onscreen UI. And while this digital conversation is bound by the restrictive confines of a television screen, its very commercial existence feels like the beginning of a new dialogue with technology on what’s achievable.

In theory, we’re wading into new territory. In truth, we’re taking our baggage with us.

The challenges we’re working to overcome as designers are diverse, and among them is a battle with our fictional history. We’re adapting the far-reaching, distinctive interfaces of the cinematic realm into usable products for a still-human world. Science Fiction has always been granted the advantage of developing UIs for a universe that embraces a cold, robotic utopia, but designers are not afforded that luxury. Most of us aren’t creating for bio-mechanical interaction where a stream of information as large as the titanic is processed on a dime in the user’s brain. We have increased our bandwidth of information intake by learned user interface intuition, but the limitations still exist.

Even more ironically, our screens are getting smaller!

We’re building products for humans, and while that fact seems to be a hot phrase to use, the implications of building products for this market should seem natural to us. Yet, in a number of cases, that couldn’t be further from the truth. We use words like “intuitive”, putting stock in the learned and natural behaviors of our audience to navigate our products; yet we’re packaging interaction guidelines to teach people how to bookmark, highlight, and turn pages. Over time, our hope is that these motor functions will become second nature.

While we’re still learning to create products for this new chapter in interaction design, let’s take the time to develop systems that work. Apple may have won their patent war, but let’s be mindful that this is arena is far from victorious. For all of their research and brand success, they’re still just a student of the new digital age like all of us. All of the answers aren’t contained within OS X, and they’re not all inside of Metro. These are the beginnings of a great dialogue that will last for a long time. You, as much as I, stand the chance to develop a more intuitive standard for this new relationship with interaction design—and the browser is only the beginning.

We’re not done discovering yet.

Not even close. 

-Justin Mezzell

11.28.12