Scheduled Downtime

There will be scheduled downtime for some Learning Lab applications during the following maintenance windows:

  • 3/5 9PM – 1AM
  • 3/7 9PM – 1AM
  • 3/9 9PM – 1AM
  • 3/10 9AM – 1PM

For more detail, please contact us via the usual channels or through your IT representative. We are aware of Sabre use during this maintenance window and it should have limited impact on decision submission.

Posted in Status | Leave a comment

Complex Forms for Many-to-Many Relationships

I have been endeavoring to learn Ruby on Rails for the past few months.  Right now I am working on a simple application that implements the Prisoner’s Dilemma problem.  You can see the data model below:

One task I found challenging was setting up a form for the Game object.  Most beginning Rails tutorials teach you how to work with only one object at a time in a form.  If you do this you can edit things like the name of the game, but that was not enough for me.  I needed to be able to associate and disassociate prisoners with a game; that is I needed to be able to work with related objects in my form.  Time to Google…

I found one approach for working with multiple objects that involves using the accepts_nested_attributes_for method and the fields_for method.  It was detailed in the following Railscasts:

  • http://railscasts.com/episodes/196-nested-model-form-part-1
  • http://railscasts.com/episodes/197-nested-model-form-part-2

Unfortunately this seemed to be more appropriate for one-to-many relationships, and it relied on a lot of JavaScript.

The approach I ended up using involved creating “virtual attributes”.  These are attributes of your model that are not directly stored in the database.  I found Railscasts #16 and #167 useful for learning about virtual attributes.

  • http://railscasts.com/episodes/16-virtual-attributes
  • http://railscasts.com/episodes/167-more-on-virtual-attributes

For my application, in my Game model, I created a created a virtual attribute “prisoner_ids”.  This is an array of integers, each one the id of a prisoner associated with the game.  I created a setter and a getter method like usual for a virtual attribute, but then I deviated a bit because in my form, when a user adds new prisoners to a game, I am required to add new records for GamePrisoner.  Rather that doing this in the prisoner_ids= set method, I chose to do it in a private function that is called by my after_save hook.  Here is the model code:

class Game < ActiveRecord::Base
  has_many :game_prisoners
  has_many :prisoners, :through => :game_prisoners

  validates :name, :length => {:minimum => 1, :maximum => 100}

  def prisoner_names
    prisoners.collect{|p| p.name}.join(', ')
  end

  # virtual attribute prisoner_ids - an array of integers
  # corresponds to the ids of the prisoners who are playing this game
  def prisoner_ids
    @prisoner_ids || prisoners.collect{|p| p.id}
  end

  def prisoner_ids=(id_array)
    @prisoner_ids = id_array.collect{|id| id.to_i};
  end

  after_save :assign_prisoners

  private

  # create or remove GamePrisoner records so that Game is
  # associated with the prisoners specified in @prisoner_ids
  def assign_prisoners
    if @prisoner_ids
      new_ids = @prisoner_ids
      old_ids = prisoners.collect{|p| p.id}
      ids_to_delete = old_ids - (old_ids & new_ids)
      ids_to_add = new_ids - (old_ids & new_ids)
      game_id = id

      ids_to_delete.each do |prisoner_id|
        GamePrisoner.destroy_all(:game_id => game_id, :prisoner_id => prisoner_id)
      end

      ids_to_add.each do |prisoner_id|
        GamePrisoner.create(:game_id => game_id, :prisoner_id => prisoner_id)
      end
    end
  end

end

In my form I used a multiselect listbox to allow the user to choose prisoners for the game.

I am happy to say, the code in my controller remains very simple.

class GamesController < ApplicationController
  def edit
    @game = Game.find(params[:id])
    @prisoner_select_data = Prisoner.all.collect{|p| [p.name, p.id]}
  end

  def update
    @game = Game.find(params[:id])
    if @game.update_attributes(params[:game])
      flash[:notice] = "Game updated."
      redirect_to(:action => 'list')
    else
      render 'edit'  ##just rendering template, not running controller function
    end
  end
end

My view also remains simple.

<div>
<h2>Edit Game</h2>
<%= form_for(@game, :url => {:action => 'update', :id => @game.id}) do |f| %>
Name: <%= f.text_field(:name) %> <br/>
Prisoners(ctrl + click):
        <%= f.select(:prisoner_ids, @prisoner_select_data, {}, {:multiple => true, :size => 5}) %>
<br />
    <div>
<%= submit_tag("Update Game") %>
</div>
<% end %>
</div>

WARNING: One place I got very stuck was in the comparison of the modified prisoner_ids and the original prisoner_ids.  I computed the intersection of these two arrays and got an empty array when I shouldn’t have.  Very frustrating!  Eventually I discovered that while my original prisoner_ids was an array of integers, my modified prisoner_ids was coming back to me from the form as an array of strings. To fix this, all I had to do was convert the strings to integers using the following line of code:

   
@prisoner_ids = id_array.collect{|id| id.to_i};

That is all. I hope this was useful. Good luck.

Posted in Blogging, Programming | Leave a comment

User Requirements

I took a Learning Tree course on developing User Requirements a month or so ago, and wanted to document some of the things that I learned during the training.

One thing that was very interesting was the delivery of the course, which impacted the way I learned. Although some students were at the physical location in Virginia, many of the students, like me, were calling in from their computers. Learning Tree calls this an AnyWare online course.

We started off with the basics, such is what is a requirement. Generally, it is something that is needed or wanted. We also talked about what they are not: verbal statements, solutions, parts of other systems, project budgets, plans or implementation details.

We then talked about the basic constraints in any project: scope, cost and time, and how when one changes, we have to make adjustments in the others.

The most helpful thing was the requirements development process. Although it is 5 steps, you perform it iteratively, refining each time to get more specific, until you have a clear set of user requirements. The five steps are: gathering information, making sense of it, creating documentation, validating your requirements, and managing change. At the end of each iteration, you should evaluate if all the requirements have been met clearly. If not, you should move through the cycle again and refine until the User Requirements document meets the needs of the users.

In class, we talked about gathering data in several ways, including conducting user interviews. It was also stressed that we should not overlook existing documentation.

A requirement must have a subject and capability, optionally it can have a criterion. The capability is limited to certain focus words which have very specific meanings, for instance if you say shall, it means that that is mandatory. They should always be in an active voice.

After the list of requirements is gathered, it’s important to validate the requirements with user walkthroughs and reviews. Without this step, you run the risk of having well defined requirements that do not meet the user’s needs.

In addition to the topic at hand, there were nice tips on being more precise in writing, which I noticed as I was writing some documentation for a simulation after taking the class. I was more focused and disregarded things that were out of the scope of the document.

Posted in Project Management | Leave a comment

The Mammoth Yearly Goals Problem

Here at Penn we are required to have a yearly job performance review, and within Wharton we’ve built upon it to be a more useful tool for our needs, while still fulfilling the Penn requirements.

But as a knowledge worker, we’re expected to complete several significant projects every year — sometimes ten or more, in a busy year. Trying to look ahead to the coming year and forecast the most important demands and how the puzzle of the year fits together would be challenging enough to be one of those goals, even without trying to allow for unexpected events (disaster recovery, new hire onboarding, etc). Then, to make matters worse, your goals are typically recorded and filed away, collecting dust and not vitamin D, until your next review a year later. Eight months into the year, it’s really hard to figure out how you’re doing on your goals. Are you ahead of schedule? Do you need to double your efforts? Are you in line for a big raise, or are you about to get canned? Who knows?! I think this is a big part of why yearly reviews are so frustrating and stressful, so I decided to do something about it.

After speaking with my team leader, we agreed to start doing…

Quarterly Goals

What do programmers do when faced with a large and complex problem? We break it down into smaller, simpler, more manageable parts. It’s just how our brains work.

Now every three months I have a formally-informal meeting (we sit in a conference room, but it’s off the record) with my supervisor, and we discuss the previous quarter’s goals and how I did compared to them, as well as planning the next quarter’s goals. This also gives us an opportunity to do any course-correction necessary to meet and exceed the yearly goals, instead of being blind-sided at the end of the year. For example, my goals for the next quarter include:

  • Operational Excellence (a standard goal we all carry at all times, which just means we try really, really hard not to screw up simulation setups, etc)
  • Demonstrable improvement to documentation for one simulation
  • Keep an outsourced project on schedule (it is scheduled to complete after the quarter is over)
  • Mentor our new hire as she learns about our organization and development stack
  • Act as project manager for a new development project we’ll be starting in the coming weeks

This list was considerably easier to come up with than trying to plan for an entire year (it took less than 5 minutes), and it is more likely to be accurate since less unexpected events happen in three months time than in twelve. In addition, I can keep this brief list bookmarked in my notebook, or pinned on the wall next to my desk as a constant reminder of the things I should be working on, should my mind start to wander.

We’ve only been using this system for about 5 months now, but I’ve already seen a dramatic reduction in my yearly-goals-based stress, and I have a much clearer picture of how my performance is perceived from further up the org chart.

Posted in Project Management, Team | Tagged , , , | Leave a comment

Educause Conference 2011

Me and my colleague Karen have just returned from attending the annual Educause conference.  I now have a collection of pens imprinted with company logos that will last me for the next several years.  I also came back with a set of new contacts, some instresting thoughts and a feeling of inspiration that I hope will last as long as the pens.


Educause is an organization that sums up its mission as “advancing higher education by promoting the intelligent use of information technology”.  While a lot of the focus of the conference was on IT related to the core administrative systems of universities, things like payroll and student records, we were able to sift through and find some things more related to what we do at the Learning Lab.

One great contact we made was Khusro Kidwai from Penn state. He has a doctorate in instructional systems with a focus on web-based learning environments.  At the conference he was presenting a poster about a web-based educational game he had created.  This game was originally paper-based and it was designed by a professor to teach students about the economics of international trade.  Khusra was particuarly interested in comparing the running of the game in its web-based form vs the running of the game in its paper-based form.  He articulated a number of advantages of the web-based game.  One advantage was the ability to embed non-educational game rules into a web interface.  For example, say there is a limit to the size of a trade.  This is not based on any economics principal, but is necessary for the smooth running of the game.  This rule can be enforced by simple form validation whereas in the past the professor would have to tell the students and hope that they would remember and obey.  The web-based form validation is convenient for the teacher and it allows the student to spend less mental effort remembering mundane rules and more mental effort on the intended lesson.  Another advantage was simply that it was faster to trade on the computer and so the number of trades at the end of the game was higher.  Additionally, analyzing data at the end of game play was much easier when that data could be found in a MySQL database rather than in piles of paper!

We met Khusro’s colleague, Chris Stubbs, who is in charge of the Educational Gaming Commons at Penn State University.  This is a group devoted to promoting educational gaming throughout the University.  They have a physical lab and have supported the development of a number of games.

Chris Stubbs, along with a colorful character, AJ Kelton, lead one of the Educause special interest groups, Games and Learning.  At the conference they hosted a discussion group focused on Educational Gaming where we discussed various topics such as what kinds of incentives can be included in games to motivate players, and why do people to work in groups so well when they play World of Warcraft.  The group has an year round email list which you can sign up for here.

Intellagirl, another potential educational gaming contact was recommended to us by AJ.  Supposedly she does work very similar to ours at the Indiana University Kelley School of Business.  I’ve taken a look at her website, but have yet to research further.

In addition to making these contacts I spent some time exploring topics outside of the educational gaming world.  One interesting discussion focused on open source software and security.  An interesting point was made that security is largly based on cryptography, and one basic tenant of crypography is that your would-be hacker should know exactly how your system works and still not be able to break the code.  However, a counter point was made that often security vulnerabilities have to do with things other than the cryptographic algorithm, and for this reason vulnerabilities would be more easily discoverable in open source software.  However if such vulnerabilities are more discoverable to would-be malicious hackers, they might also be more likely to be fixed… and the discussion went on.

Another interesting talk was given by Danah Boyd who studies young people’s use of social media.  In this talk she focused on some creative and unconventional ways that kids use facebook to achieve certain types of privacy.

All in all the Educause conference was a good time.  I look forward to interacting with some of the people we met and I have lots of ‘food for thought’ on several topics.

Posted in Conferences | 1 Comment

Setting goals based on objectives

One of the key objectives I had when I started heading the Learning Lab was to improve operations. This means making sure that simulations are setup and executed correctly.

Some difficulties

One thing that makes such a seemingly straightforward task difficult is the turnover on the team. The team veteran has been here less than three years, and we’re working with applications developed between 1997 until today. Although there are setup instructions, they are often written by the developer of the application who makes assumptions about the audience’s knowledge about the application.

That applications were setup and executed primarily by their developer is another artifact of previous policy that makes operations more difficult.

The Goals

In taking the reins, I decided to implement three team-wide goals that attempt to address the problems above:

  1. Assign team members to be “product managers” of applications, dividing them by skill level, complexity, and experience. Make product managers ultimately responsible for their applications by adding a goal:

    No major errors in any applications I am product manager of.

    Although at first glance, this goal puts the same level of responsibility that existed when a developer was responsible for her own application, the other two goals work to distribute this responsibility.

  2. This goal seeks to encourage teamwork:

    No more than one major error in an application I am NOT product manager of.

  3. And, finally, this goal works to document the knowledge spread throughout the team, not only for us, but for those who come after us.

    Complete these pieces of documentation for all applications I am product manager of:

    • User manual
    • User walk-through screencast
    • Administrator manual
    • Administrator walk-through screencast
    • Setup manual
    • Setup walk-through screencast

Intentions

In implementing these goals, it was important that I also share them. Where the team fails, I have failed most of all. If the team succeeds, only then will I have succeeded.

These goals are intended to work together so that team members work closely together to avoid mistakes. Some of the problems are due to development issues, but some are just due to human fallibility. We can limit problems caused by both of these by working together, with deliberate thought, clear practices and policies, and by thinking not only of ourselves, but of the organization which we represent, and all of those that might come after.

Posted in Team | Tagged , , | Leave a comment

Installing Rails 3.1.0 on Ubuntu 10.04 with MySQL

The Learning Lab is working on a new project, Byrd, which will allow students to give real-time feedback to their instructors during a lectures.  Byrd will be the first project that our group will develop using Ruby on Rails.  As the only member of my group who does not use a Mac, I had a bit of a challenge trying to install things properly and get a working Rails development environment.

What follows is a recount of what I had to do to get things working.

First I installed VMware Player, a free product from VMware, onto my Windows laptop.  Then I downloaded an .iso for the installation of Ubuntu 10.04 LTS.  In VMware Player I created a new virtual machine using this Ubuntu iso file.  When the machine was created, I started it up and I let Ubuntu run its initial software update.

Now the challenging part… getting a Rails project to work!

First, on my Ubuntu machine, I opened a terminal window and ran the following command to install some necessary libraries.

sudo apt-get install curl git-core build-essential zlib1g-dev libssl-dev libreadline5-dev

I chose to use RVM(Ruby Version Manager) rather than installing Ruby directly on my machine.

Detailed RVM installation instructions can be found on the RVM website.
I’ve included only a brief summary of these instructions.


$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
$ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile

Now I close this shell and open a new shell.

$ rvm list known #should list all kinds of ruby versions to choose from

$ rvm pkg install zlib
$ rvm pkg install readline
$ rvm pkg install openssl

$ rvm install 1.9.2 --with-openssl-dir=$HOME/.rvm/usr

$ rvm --default use 1.9.2

$ gem install rails

Hooray, Ruby on Rails is installed using RVM!
Now you need a few more things in order to get rails project working, such as a database engine and a Java runtime environment.

Rails uses SQLite by default so you much install this to your machine


sudo apt-get install sqlite3 libsqlite3-dev
gem install sqlite3

Now make your first rails app:

rails new <your app name>
cd <your app name>

open up the file Gemfile and add these two lines

gem 'execjs'
gem 'therubyracer'

then in the terminal

bundle install

Now try out the following to make sure that they work:


rails server
rails generate model Dummy id:integer name:string
rake db:migrate
rails destroy model Dummy

Hopefully everything is good so far.  For the Learning Lab’s Byrd project we will use the MySQL database instead of SQLite.  Here is how to do that:

I open up my config/database.yml file and deleted/commented everything in it.  Then I added the following.


development:
adapter: mysql2
encoding: utf8
database: testapp
pool: 5
username: root
password:
socket:

Next I install MySQL on Ubuntu


sudo apt-get install libmysqlclient-dev mysql-server

I left my root without a password, if I added one I would need to add that password in my config/database.yml.

Next I open up my Gemfile and add the line

gem 'mysql2'

Now finally I should be able to run the following commands


rake db:create
rake db:migrate

And voila!  I have a working Rails project on my Ubuntu virtual machine that uses a MySQL database.

An afterthough – I installed the programs Meld and SQL Query Browser.  I find both very helpful for my Rails development.

Good luck!

Some of my specs:
VMware Player 3.1.4
Ubuntu 10.04 LTS
Ruby 1.9.2 p290
Rails 3.1.0
MySQL

Thanks to the following sites:
http://beginrescueend.com/rvm/install/
http://www.web2linux.com/05/installing-rails-3-on-ubuntu-10-04-lucid-lynx/

Posted in Uncategorized | 1 Comment

A New Team Member Starts

We’re really excited about our new team member. Not only is there a lot of work to get done, it also gives us a chance to test some of our onboarding procedures.

I have been putting a lot of thought into what order to introduce material in, and what sequence tasks should be given in. For example, is the top priority on the first day setting up ones equipment or meeting everybody in the office? What kinds of software should be installed in the first couple hours of work? You could opt to setup a development environment to get started on tasks as quickly as possible, or install communications software such as e-mail and messaging clients.

New Hire Checklist

We have had an onboarding document started by a previous Learning Lab director. It was very instructive, but it had a mix of tasks for both the new hire and his/her supervisor. Separating this document into two, one for the new hire and one for the manager, was one of my first decisions. There was just too much clutter that the new hire didn’t have to see.

The document was a large, monolithic checklist of items. I changed it, categorizing tasks temporally into three categories called: before the first day, the first week, and subsequent weeks or as-scheduled. The supervisor checklist was also categorized into separate temporal categories: at least two weeks before, at least a few days before, before the first day, and the first day. These categorizations critical to making sure new employees having everything they need on day 1. PENN is a really large organization, and there are some things that take weeks to happen.

Finally, I added notes about what the Learning Lab is, how to find out more about it, and an organizational chart. I’m a big believer in Organizational Charts, and think they are critical to getting your bearings when you start somewhere new.

Hello, nice to meet you!

I asked the new team member to prepare a short biography to send to the staff mailing list to introduce her. The morning she started, I sent the e-mail right away to prepare everyone for the new face.

That day, I introduced her to many of the people in our office at St. Leonard’s Court. Later on, we went over to Vance Hall to introduce her to a few key people in that office. I printed a copy of the Organizational Chart so she could see where the people she met fell in the organization. Other introductions occurred mostly organically, but last week I made sure to introduce her to more of the people who work in Vance Hall. I am a strong believer in meeting people face to face. It’s the best way to start a working relationship with someone.

In the coming weeks, our new team member will be meeting with the Senior Directors that manage Wharton Computing, and also the Directors that manage our subgroup, Custom Applications.

These introductions not only help employees understand where they fit in the organization, but is also a tactic to break out of the silos that are common in an organization as large as ours.

Ready Day 1

The new team member has come in and was able to start contributing day 1. To make sure this can happen, a supervisor needs to be on the ball and have a bit of foresight. It’s tedious, but a supervisor has to make sure that:

  • Equipment is ready and waiting
  • Building access works
  • The office space is all setup, including a desk, phone, and chair
  • Accounts have been created
And there are still many other things a supervisor can do to make sure the transition is smooth. These are some of the most critical, but even these are missed sometimes.
Posted in Team | Leave a comment

Finding Volunteers

Although the MGMT 652 simulation is in its third year, this was the first year that I acted as Project Manager. One of the biggest challenges I faced was finding volunteers to assist with the technical needs of the simulation. While what I am writing about is specific to this project, there are many ideas that can be taken away and used in any project that happens infrequently.

We have an awesome staff that is always willing to help out, but the end of August is one of the busiest times of the year for Wharton Computing. I thought I would talk about some of the strategies that I used (or thought about using) in order to get the support at the level we needed to ensure success. The long and short of it is to be respectful of your colleague’s time, and thank them in any way you can.

Make it easy
Clearly communicate when you need them, where they should meet, and what the requirements will be. Even if you send them information ahead of time, be sure to have a copy of documentation for each volunteer, so that they have everything they need. Prepackage any supplies or equipment they will need and be ready to go when they show up.

Thank them
Be sure to thank them at every opportunity, especially sharing great support with their supervisors. If someone is going above and beyond to help you be successful at your project, the least you can do is thank them.

Give them food
If you are having a hard time recruiting for a task, especially one that may be long or tedious, the best way to sweeten the pot it to include food. We provided lunches for an all day beta test, as well as to a group that helped us set up two computer labs in classrooms. For those who were required to be present during the simulation, there was a room full of catered food from morning until evening.

Outsourcing
We had the former Project Manager come in as a consultant in order to ensure continuity and make sure nothing fell through the cracks. It worked out beautifully.

Make it as clear as possible for the next PM
One thing on the checklist from last year was to make sure the classrooms that got set up as labs had an AC boost. Some of us thought that meant Air Conditioning, while others thought it meant electric. Also be clear if there are multiple departments working on the overall project to be sure that you aren’t working on the same tasks. For instance, I asked a department about how students were entered into the sim, only to find out that that someone else was handling it. Since it was still on the checklist from last year, I was not aware of the change.

Have an AAR
It’s important to wrap up the project by finding out what went well, what could have gone better, and share lessons learned. It allows people who were involved to share things that happened that you may not have been aware of.

Take time for reflection
Be sure to take some time when your project is over to update documents and make sure everything is ready to go for the next time. You could be saving the next PM hours by clearly explaining what happens during the project and some background as to why.

Posted in Project Management | Leave a comment

Taking the next step

Something I spend a fair amount of time thinking about is what’s on the horizon. What sorts of things should we be learning and implementing to make ourselves better developers and a better team, as a whole?

Part of that involves knowing what we already do, and in some cases, do pretty well.

  • We have a pretty well defined code-review process and we try to integrate as much feedback from them as possible.
  • We are getting better at creating automated tests to make long term application maintenance easier.
  • Some of our applications have ANT scripts that make producing Production builds (combined, minified JS + CSS, etc) easier
  • We’re using Distributed Version Control (git) like a champ, now!
  • We pair program, when possible. (It can be difficult to find significant chunks of matching free-time on a small team.)
  • We’re starting to expose some of our reusable code as REST API’s so we don’t have to waste time copying and re-integrating them into every application

So knowing what we do well, what are the logical next steps? What should we learn and do to continue growing and taking those next steps? Here are some ideas and my thoughts on each. These are just some things I came up with off the top of my head. What else do you think could be useful?

Chef

Our colleague Lew G has written at some length about his experience learning and using Chef. It sounds wonderful! It sounds ideal! It sounds like it could be kind of… hard.

For one, our group has only one server that we manage currently, and it runs on Windows. The rumor mill says that the Chef support for windows is not nearly as good as it is for unix/linux. Of course, this is third- or fourth-hand information, and subjective at that; so it bears some investigation.

You may be able to find people who would argue against automated server configuration like this, but I doubt any of them will be from our team. Being small means that we have to think about our agility and plan ahead for the worst case scenarios or continually find ourselves dealing with the fall out from the previous week’s issues. Having one or two people spending two or three days recovering from a total server loss would be catastrophic to our team productivity. Learning Chef and writing/testing scripts (“recipes”, right?) to rebuild a server quickly and at a moments notice would definitely go a long way in our personal DR plan.

Jenkins

Continuous integration is the holy grail of automated testing, and with Jenkins now so available and approachable, it’s never been easier. How nice would it be to make a commit to source control, and then a few minutes later get an IM letting you know whether or not the tests are passing? Pretty darn nice! … And just the tip of the iceberg, of course.

Document-based data stores / NoSQL

I recently did a one-day workshop for Hadoop and learned a lot about it and its sibling nosql/document databases. The biggest takeaway for me and our team was something the trainer said. I’m paraphrasing from memory but he said something like, “If you’re not working with 1TB of data or more, NoSQL is not for you.” I don’t think the Learning Lab has 1TB of data from all of our applications combined (maybe not even breaking into double-digit gigabytes), so it’s not really an obvious win for us.

That doesn’t mean there’s no place for NoSQL in the Learning Lab, though. Suppose we need to write an application that will need to support 10,000 concurrent users for a short period of time. Given a Chef script, it could be pretty simple to spin up a few dozen Cassandra/Couchdb/etc nodes to scale as wide as needed, and adjust on the fly according to performance. I imagine scaling a system like this would be much more manageable than trying to get a single machine powerful enough to run MS SQL at the same scale on a temporary basis (Not to mention the licensing costs, since MS SQL is licensed based on the resources it has available!). So while we probably won’t dive into this topic right away, we should keep it on our periphery.

LESS CSS

CSS is a very powerful, and when used well, terse way to style html documents. But it can be a pain in the rear to use. Over time stylesheets tend to grow to unmanageable size, and it’s incredibly difficult to write them DRYly. Enter LESS CSS. To quote a friend of mine, LESS “makes CSS think like programmers do.” You can create and use variables and functions, include files, and much more… and it all compiles (almost instantly, from what I hear) to the native CSS we know and … erm… love (?) today.

Posted in Programming | Tagged , , , | Leave a comment

University of Pennsylvania Logo
Copyright © 2012 The Wharton School, University of Pennsylvania