Advertisement

10 Things I Learned While Interning at YUI

by

For eight months, I had the opportunity to intern with the YUI Team at Yahoo, while I was completing my engineering degree. Today, I'd like to share the top ten things that I learned from my experience with YUI.


A Bit of Background

The YUI Team is primarily responsible for the development and maintenance of the YUI Library. The library is a collection of user-interface components, class management tools, and utilities written in JavaScript and CSS that make it easier for developers to create web applications. Unlike other libraries, YUI is not just about DOM manipulation; it has a rich set of class management tools and a robust event system that makes it easier to develop in JavaScript.

Apart from that, the YUI Team is also responsible for YUI Theater, a very popular resource for web developers, along with a myriad of smaller tools such as YUI Builder, YUI Compressor, YUI Test and more.

My role at the team was to primarily help develop components for the library, although I helped out a little bit with YUI Theater as well.


1. Understanding the Library

When I walked into Yahoo on my first day, I had zero real-world experience with YUI. I was familiar with JavaScript, jQuery, HTML/CSS and PHP, but that was basically it when it came to web programming. I'm sure many of you are or have been in the same boat as me.

My first task was to learn the syntax and architecture behind YUI3. Fortunately, I had a good understanding of raw JavaScript, and this helped immeasurably. A lot of front-end engineers know certain libraries really well, but many don't know how they works under the hood. To build plugins or modules on top of a library (such as YUI3 or jQuery), it's useful to have a fundamental understanding about how that library works, and in this case, how JavaScript as a language works.

What I learned: Having a fundamental understanding of raw JavaScript (no libraries) forces you to understand the language better and makes you a better developer in the long run.

Think about it. Each JavaScript library is different and has its own idiosyncracies. The only commonality is that they are rooted in JavaScript. Doesn't it make sense to understand the idiosyncracies of JavaScript first? Take some time out to build something small without using a library. You'll be glad you did.

Js Fundamentals Links


2. Using Git in a Team

The YUI Team relies on Git as their primarily version control system and the project is hosted on Github. Previous to my internship at YUI, I used Git for my own small projects, and this generally consisted of the following steps:

  1. git pull origin master
  2. git add "<insert a large number file>"
  3. git commit -m "<insert some general comment>"
  4. git push origin master

I'm sure many of you have done what I just described. Generally, as the project time gets longer, the commits get harder to understand! However, in a large team with a dozen developers, this method breaks down really fast. Firstly, master in YUI3 (and many other large projects) is considered to be stable code that has been unit-tested, so commits generally do not go there until a later stage. Generally, each developer works on a separate branch and merges into master once they are confident in their code.

What I learned: You don't have to be a guru, but understanding the basics of Git (branching, merging, reverting and solving merge conflicts) can go a long way to keeping your repos clean and organized.

A lot of things are possible to do with Git and I've found that, rather than learning them ahead of time, it's more useful to research when you need to do something in particular. More importantly, my experience has taught me to be careful when experimenting with Git. It's better to ask someone when trying a new command or trying it on a mock repo instead of messing up the commit history of the live repo. :)

Git Basics Links


3. Modular Architecture for Web Apps

Separating code into different JavaScript files to maintain a modular architecture can be painful for new developers. As a result, we often see large JavaScript files with hundreds of lines of code in them.

<DOCTYPE html>
<html>
    <head>
    <script>
        //My entire application's JS right here in one single spot. Uh oh. 
    </script>
    ...

This introduces tight coupling between objects and isn't good practice when it comes to object-oriented programming. Even worse, you may have global variables that makes your app fail in unexpected ways. We've all been guilty of this in the past. Luckily, libraries like YUI can help you with this.

What I learned: When writing an entire web application in JavaScript, it’s very important to have well-organized code; maintaining a spaghetti-coded project will only cause you headaches and nightmares.

One of the most important aspects of YUI3 is its modular nature. As a developer, you only pull down the code that you need. This reduces coupling, keeps file sizes small, and improves your code's readability.

For instance, you could do this in a file called counter.js:

YUI.add("counter", function(Y) {

    //Write code specific to my counter object

}, '1.0', {requires: ['node']); //Say what my counter object code needs to run. YUI will pull these in first.

And then in a separate JS file, such as app.js:

YUI_config = {
    modules: {
        'counter': { fullpath: 'path/to/counter.js', requires:['node'] }
    }
};

YUI().use('counter', function(Y) { //Pull down my counter module.
    var counter = new Y.Counter({…}); //Create a counter instance
});

Instead of having one big file called app.js, we've split it up based on functionality into counter.js and app.js.


4. NodeJS and YUI on the Server

The growing popularity of NodeJS made me want to start building some stuff with it. Being a front-end engineer, I like being able to use JavaScript on the server. Although NodeJS is not suitable for everything, it's worth learning.

JS on the server does not have the same limitations as client-side JS because there is no DOM, but a library such as YUI can still help you with software architecture on the server - things such as class and object management, and custom events.

What I learned: YUI 3 is not all about DOM manipulation — it also contains a robust set of class/object management tools, not to mention our powerful custom events. All of these tools are immediately useful in server-side programming.

Being on the YUI Team, I was able to explore Dav Glass' NodeJS-YUI3 module, which wraps up YUI functionality for use in a NodeJS environment. Remember that, apart from web sites, NodeJS is a useful tool for creating command-line utilities as well. Having good software architecture is always a big plus!

It comes down to code management

If you aren't a YUI3 user, I still recommend finding a set of tools to help organize your JavaScript on the server. Due to the inherent async nature of JavaScript and its propensity for callbacks, you need to be careful or you'll quickly end up with spaghetti-code.


5. Hacking Using YUI

What I learned: Stay focused and keep hacking.

Hacking is one of my favourite things to do when I am trying to learn something new. When trying to learn a new tool, there's nothing like sitting down and building something with it.

Similar to jQuery, YUI3 has a distinct set of widgets, utilities and CSS frameworks. On one of the Yahoo Hack Days, I had the chance to sit down and try some of these out. As I'm a fan of cricket, I made a mobile web app called Crictainment. Let me outline some of the parts of YUI that I found to be particularly useful for hacking.

Crictainment mobile web app using YUI

Y.ScrollView

Hacking a web app using YUI is pretty straightforward. For example, if you want a scrollview that is flickable with your fingers:

YUI().use("scrollview", function(Y) {

    var scrollview = new Y.ScrollView({
        srcNode:"#scrollable",
        height:"20em"
    });

});

And in the HTML:

<div id="scrollable" class="yui3-scrollview-loading">
<ul>
    <li>AC/DC</li>
    <li>Aerosmith</li>
    <li>Bob Dylan</li>
    <li>Bob Seger</li>
    ...
</ul>
</div>

The scrollview module figures out whether it should be horizontal or vertical based on the width and height of its container. More information on the YUI3 scrollview is here.

Y.Anim

Another useful utility when hacking something is the Animation utility. It helps to spruce up your application with some nice animation that leverages CSS on capable browsers, and defaults to JS timer-based animations on older browsers.

var myAnim = new Y.Anim({
    node: '#demo',
    to: {
        width: 0,
        height: 0
    }
});

myAnim.on('end', function() {
    myAnim.get('node').addClass('yui-hidden');
});

Y.YQL

Another really important tool that is great for hacking is YQL - Yahoo Query Language. I'm sure most of you have used it, but for those who haven't, think of it as a way to access a whole host of different APIs using a standard syntax. YUI and YQL work really well together through the Y.YQL module. For instance, here we are getting the recent activity from Vimeo:

YUI().use('yql', function(Y) {

    Y.YQL('select * from vimeo.activity.everyone where username="basictheory"', function(r) {
        //r now contains the result of the YQL Query
    });

});

Try out this query here. I use YQL regularly to access different APIs in a consistent manner.

Regardless of whether you are using YUI, jQuery, or any other library, building something with it is a great way to become familiarized with your development toolbox. When hacking, don't worry too much about the technical details - just set a time limit and just build it!


6. YUI App Framework

One of the newer additions to YUI has been the App Framework. It's similar to Backbone.js, but with YUI's sophisticated event infrastructure under the hood. The App Framework made it easy for me to build MVC-style web applications.

Just like any other tool, I built something with the App Framework to understand how it worked. Once again, I can't stress the benefits of hacking on products. For the App Framework, I built TopForty with a friend of mine.

TopForty web app using YUI App Framework

The Model

The YUI App Framework is built on the MVC design pattern. Let's start with the model. If you aren't familiar with MVC, take a look at this tutorial.

For TopForty, we were able to get a large JSON array of the most talked-about songs from Twitter. Each object in the array looked like this:

{
    "title": "PayPhone",
    "position": 1,
    "video_id": "5FlQSQuv_mg",
    "song_id": 627,
    "artist": "Maroon 5",
    "duration": 232,
    "images": […]
}

We wrapped this up in a Y.Model subclass called Y.SongModel. Here's the class definition:

Y.SongModel = Y.Base.create('songModel', Y.Model, [], {

    initializer: function (config) {
        ...
    }
}, {
    ATTRS: {
        title: {},
        artist: {},
        images: {
            value: []
        },
        nowPlaying: {
           ...
        }
        ...
    }
});

This allowed us to listen for events whenever one of the ATTRS in the model changed and take appropriate action. For example, if the current song being played was changed:

//When the model's isPlaying attribute changes, call the handleIsPlayingChange function.
this.model.after('isPlayingChange', this.handleIsPlayingChange, this);

The View

Each model was represented visually by a View, which is essentially just HTML. For TopForty, we had a SongView that looked something like this:

<div class="song yui3-u" id="songModel_2">
            <img class="song-img" src="...">
            <div class="song-desc">
                <div class="song-number">2</div>
                <div class="song-movement">
                    <img class="movement-icon" src="...">
                </div>
                <div class="details">
                    <h4 class="song-name">Turn on the lights</h4>
                    <p class="artist-name">Future</p>
                </div>
            </div>
</div>

We wrapped this up in a Y.View subclass called Y.SongView. Each View requires a render() method that is called when displaying the view on the page, and a initializer() method where events are subscribed. If you want, you can establish a relationship between your view and a Model or Model List instance by attaching event handlers to them in a custom initializer() method like we see below:

Y.SongView = Y.Base.create('songView', Y.View, [], {
    initializer: function (config) {
            var model = this.get("model");
            model.after('change', this.render, this);
            model.after('destroy', this.destroy, this);
    },
    render: function() {
        ...
    },

    destroy: function() {
        ...
    },

    showSongOverlay: function() {
        ...
    }
},{ 
    ATTRS: {
        container: Y.one("#songContainer")
    }
});

By doing this, we were able to have songview specific methods such as displayNowPlayingIndicator() and showSongOverlay() on the Y.SongView instance rather than as separate functions.

The Router

The Router, formally known as the Controller, is what makes everything connect and work. Remember that in classical MVC, all user actions traditionally go through the controller. In web apps, the router uses HTML5 history to change URLs and controls the state of the application.

For example, in TopForty clicking on a song changes the URL to the song's ID. The URL change is picked up by the router, which loads the YouTube video for the song in question:

Y.AppRouter = Y.Base.create('appRouter', Y.Router, [], {
  // Default route handlers inherited by all CustomRouter instances.
  index: function (req) {
    // ... handle the / route, load up the UI, etc.
  },

  loadSongFromUrl: function (req) {
    // ... handle the /song/:songId' route ...
    //Get the youtube video from the model with an id of :songId and play it.
  }
}, {
  ATTRS: {
    // The specific routes that we are interested in listening to:
    routes: {
      value: [
        {path: '/',    callback: 'index'},
        {path: '/song/:songId'', callback: 'loadSongFromUrl'}
      ]
    },
  }
});

What I learned: Leveraging the MVC design pattern can help you create anything from simple non-interactive views to rich applications.

I hope I have been able to give you a taste of what is possible with the YUI App Framework. For a more thorough walkthrough, I recommend the following links. If you aren't a fan of the App Framework, I recommend you look into the equivalent jQuery alternatives. Backbone.js in particular has a large following with good documentation.


7. Test Driven Development and YUI Test

For developers, writing code is often the easy and fun part. The hard part is figuring out how old, buggy code works and trying to fix past errors. To minimize this, a lot of organizations including Yahoo emphasize the importance of Test Driven Development (TDD). With TDD, you write the tests first, then add the functionality until all your tests pass. Want to add a new feature? Write a new test, then code the feature.

I was new to TDD when I joined the YUI team. Unfortunately, JS does not have the best testing suite. User interactions in particular are hard to test. Furthermore, we have to test in all the major browsers.

One of the primary ways we conduct unit-testing is through YUI Test.

What I learned: Following test-driven development principles makes you more productive as a programmer.

YUI Test is a complete testing framework for JavaScript and Web applications. You can use the simple JavaScript syntax to write unit tests that can be run in web browsers or on the command line, as well as functional tests to be run in web browsers.

Here's how you set it up:

// Create a new YUI instance and populate it with the required modules.
YUI().use('test', function (Y) {
    // Test is available and ready for use. Add implementation
    // code here.

});

Now, we can start writing some unit tests!

var testCase = new Y.Test.Case({

    name: "TestCase Name",

    //---------------------------------------------
    // Setup and tear down
    //---------------------------------------------

    setUp : function () {
        this.data = { name : "Tilo", age : 23 };
    },

    tearDown : function () {
        delete this.data;
    },

    //---------------------------------------------
    // Tests
    //---------------------------------------------

    testName: function () {
        Y.Assert.areEqual("Tilo", this.data.name, "Name should be 'Tilo'");
    },

    testAge: function () {
        Y.Assert.areEqual(23, this.data.age, "Age should be 23");
    }
});

YUI Test supports equality assertions (areEqual()) which uses ==, sameness assertion (areSame()) which uses ===, special value assertions such as isFalse(), isNotUndefined(), mock objects and more.

After writing our tests, we can run it as shown below. The results of the test can be outputted as XML, JSON, jUnitXML, or TAP.

Y.Test.Runner.add(testCase);
Y.Test.Runner.run();

Don't forget to test, regardless of what you use.

If you don't use YUI Test, that's fine. However, I want to stress the importance of testing your code. I'm guilty even today of writing code without writing tests and it's probably okay if it's your own small personal project. All of us cut corners sometime. However, if you're programming for a client or an organization, following TDD principles will save you (and your clients) from a headache.


8. Minifying and Linting Your JavaScript

Serving up JavaScript files without any minification or lint step can be risky. Minification can often compress the file-size by over 30%, making your page load faster for the end-user. Linting is a good way to ensure your JavaScript follows good coding practices so that errors are minimized.

During my time at Yahoo, we used YUI Compressor and YUI Builder to compress and build our code. The build step includes concatenation and linting through JSLint. I'm sure most of you have used JSLint at some stage, and I do believe it helps improve your coding style.

What I learned: Ask yourself if a certain practice reduce your possibility of errors and if so, follow it.

Now, I'm not going to talk in depth about YUI Compressor and Builder because those may not be the tools of your choice. Usually for my own projects, I use the JSLint NPM Module to check my code.

What I want to stress on is the need to perform these steps prior to pushing code out to production. As JavaScript does not have a compilation step, many developers are accustomed to pushing their JavaScript out to production, comments and all included. Again, this is okay for small projects, but perhaps you should consider minifying and linting your code to ensure users get the best experience.

Additional Reading


9. Coding with the User in Mind

The YUI Team has a great following of friendly, active, and knowledgable developers just like most large open-source projects. As developers working on open-source software, I learned that I can't sit under a rock and code all day, even if I want to. Developing is as much about writing code as it is about making sure the code you write is actually helping someone solve a problem.

This took me a while to learn, but it's an important lesson. When writing software, the goal isn't to use the coolest technology or the latest stack or the hottest language. It's about the user. When writing OSS, the users are often other developers who build on top of your product. Small things such as weekly updates, tweets, and IRC communication can actually help you more than hours of coding.

What I learned: It's not about the technology or the stack or the language, it's about the user.

In my first month of interning at YUI, I wrote about 500 lines of code which I had to scrap because most of it was repetitive and did not address the end goal. I was guilty of coding too early without figuring out the requirements of the project. A good rule is to spend a third of your time gathering requirements, a third of your time writing tests and the final third implementing your software.


10. "When all you have is a hammer, everything looks like a nail."

I want to conclude by sharing the most important thing that I think I learned in my internship. I consider it to be more important than any technical knowledge that I gained. By working on a library that is not the most popular, I realized the importance of diversifying my skills and being flexible as a developer. I've seen how much work it takes to maintain an open-source project and have gained a lot of respect for everyone who release their well-written code for free.

What I learned: Choose a library because it's the right one for the job, not because it's your favourite. Understand that different pieces of software serve different purposes, and sometimes understanding the difference is tough.

Advertisement