Blog


Dec

Has Microsoft become altruistic or is cooperation simply better than competition?


The market economy prides itself on its competitive nature. Through competition we’re promised better and cheaper products and services. I believe this to be true in countless cases. I also believe that we need to be better at considering both the benefits and the inefficiencies that the competitive model brings. As with any dogma it can do just as much harm as good unless constantly being evaluated from a case-to-case perspective.

Retrieved from http://www.teslamotors.com/models/photo-gallery

Consider for example what companies do to protect their investments in research and development. Companies are constantly suing each other over patents and spending billions on lobbying to make IP-laws stricter and more far-reaching. We buy this concept because we believe competition is more effective than cooperation. It’s been this way for so long that it’s hard to even imagine the alternative. Who knows what kind of cars we would have if all the car manufactures cooperated in their RnD. Maybe we would all have been driving the Tesla Model S ten years ago, maybe we would still be stuck in a Trabant, who knows?

Given this blog post being on a software development firm’s blog you’ve probably already figured out where this is going. Open Source is a large-scale, unconditional, more or less all-in choice of cooperation before competition, and it works! 59% of all web sites run on open source web servers. 95% of smart phones run on open source technology. 82% of users access the Internet using a web browser built on an open source foundation. With Microsoft’s recent release of the .NET framework as open source pretty much all major programming environments are now open source.

Retrieved from http://www.flickr.com/photos/gforsythe/8174197748/ Illustration by Giulia Forsythe

In my experience open source projects tend to be numerous and diverse, allowing the user to choose a project that suits their needs. Often times they have large and helpful communities, answering questions in time zones all around the globe. Open source products are often free, and thus available to more users. Simply giving more people access to others’ creations can spawn innovation that would be lost in a closed environment.

As a software consultant I know that trust is key. When there is lack of trust there is legal overhead, misinformation and static control structures that prevent agility. These projects tend to be more expensive and deliver inferior results. Open source requires a whole bunch of trust. Put yourself in Microsoft’s shoes. Would you find it easy to “give away” technology that you’ve spent billions developing? You’d need to put your trust in people you’ve never met, hoping you will get back as much as you’ve given.

Open source in the software industry might be the most obvious example of trusting others to do something great(er) together. But in fact our entire civilization requires us to trust in each other. Without trust currency would be hugely inconvenient, e-commerce would be impossible and we would have no taxes to pay for services such as law, defense and education.

I don’t believe every sector would benefit from unconditional cooperation but I’m certain that there are vast possibilities to create better, cheaper, fairer, and safer products and services if we start trusting each other more!

Which sectors do you think would benefit from replacing competition with cooperation? How can the software industry benefit from even more cooperation? Or have we gone too far? Use the comment section below!

Nov

Refile: Fixing Ruby File Uploads


Six years ago, Merb was on the scene. I was one of its acolytes. I wanted a nice upload plugin for Merb. Since I had some experience in this area from writing (never popular) UploadColumn, I wrote one. It was called merb-upload, and my intention was for this to eventually become part of merb-more. You've probably never heard of merb-upload, but you may have heard of what it eventually became. It slowly grew Rails support, and to reflect the diversification, I renamed it CarrierWave.

It actually took a while for CarrierWave to become succesful, so it was the new kid for the long time, but it's actually only about a year younger than Paperclip. While both of these libraries, the two most popular for file uploads by far, have changed drastically over time, they are nevertheless both over six years old.

A lot has changed since then.

Over the years I've been contemplating what I would have done differently if I had to do it all over again.

  1. CarrierWave's killer feature is fixing file uploads to work even if validations failed and the form needs to be redisplayed. Unfortunately this has never worked reliably when files were uploaded to S3.

  2. Processing files on upload can be prohibitively expensive, and CarrierWave doesn't provide a good solution to this. When the size of an image should be changed CarrierWave requires re-processing all files. Dragonfly has a much better solution to this problem: processing images on the fly and serving them up directly, behind a CDN.

  3. Direct to S3 uploads are cumbersome. I find myself needing this time after time, and while there are bolt-on solutions, nothing really feels very solid.

  4. The internal design of CarrierWave is just far too flexible and strange. Uploader classes, while a nice relief from the monstrous configuration in model classes that other plugins require, are also quite brittle. I also found myself never actually using any of the insane flexibility that CarrierWave provides. It's really hard to figure out what actually happens inside CarrierWave.

  5. The integrations have changed. When CarrierWave was written, Ruby web frameworks were different than they were today. Rails 2.3 with support for Rack wasn't released until a year after its inception. Merb was a serious contender. As a result, there's a lot of boilerplate in CarrierWave which isn't really necessary.

All of these problems have been on my mind off and on again over the past couple of years. Even though I haven't been involved in the CarrierWave project in years, I still found myself unsatisfied with its current state, and with the status quo of file uploads in general.

So I wrote a new one. This is my third attempt at a file upload plugin, and I'm hoping that this time, maybe I got it right.

It probably isn't for everyone. It's far, far more opinionated than CarrierWave or Paperclip. I don't expect it to outright replace either. But if you're looking for something which is simple, where you can get direct to S3 uploads with the addition of a single config option, where you don't really have to think about how and where files are stored. This may be the one for you.

It's called Refile. Please check it out and let me know what you think. All feedback and especially all contributions are very welcome.

Feb

Using websockets in native iOS and Android apps


This is an example of using websockets to communicate in real time from browser, iOS, and Android clients.

Why would we want to do that? Since the same real time backend can be reused for all platforms, we can keep the architecture simple and the number of distinct components that can fail to a minimum. Or maybe we just want to add a native client to an existing web service that already uses websockets, without having to change stuff on the backend. This post will demonstrate that it is quite straightforward to connect to a websocket server from iOS and Android as well as from the browser.

We recently used this approach in the Need for Speed™ Network application, which is available for all three platforms. Check out the trailer video on YouTube to see it in action. We used websockets to send the real time in-game positions of the user's friends in order to display them on a map, among other things.

The websocket client API is very simple, and is pretty much identical across the different client implementations used in this example. Adding TLS encryption is also pretty easy from the client's point of view, since we just need to change the ws:// URL to a wss:// one.

The example app is a simple chat service. There are no separate channels or nicknames to keep it as bare bones as possible. When a new client connects, it automatically sends a message including what device or browser it is running on.

The full example code (server and the three clients) is available at https://github.com/elabs/mobile-websocket-example. The apps are very basic and only intended to show how to use the API - they contain very little error handling, no tests, are not prepared for localization, etc.

Server

This is a basic websocket server implemented in Ruby using the EM-WebSocket gem.

Here is the entire code for the server implementation:

require "em-websocket"

EventMachine.run do
  @channel = EM::Channel.new

  EventMachine::WebSocket.start(host: "0.0.0.0", port: 8080, debug: true) do |ws|
    ws.onopen do
      sid = @channel.subscribe { |msg| ws.send(msg) }
      @channel.push("#{sid} connected")

      ws.onmessage { |msg| @channel.push("<#{sid}> #{msg}") }

      ws.onclose { @channel.unsubscribe(sid) }
    end
  end
end

The server accepts websocket connections on port 8080. When a new client connects, it subscribes to an internal channel. Every time a client sends data it is pushed to the channel, and when new data is available on the channel, it is sent to all connected clients. Clients are identified by their subscription ID which is an incrementing integer. When the client disconnects, it is unsubscribed from the channel.

To get the server running, run bundle install and then ruby server.rb.

Browser client

The biggest reason to use websockets in the first place (instead of, say, regular sockets) is that they are possible to use from a modern browser context. The JavaScript code looks like this:

$(document).ready(function() {
  ws = new WebSocket("ws://" + location.hostname + ":8080/");

  ws.onmessage = function(event) {
    $("#messages").append("<p>" + event.data + "</p>");
  };

  ws.onclose = function() {
    console.log("Socket closed");
  };

  ws.onopen = function() {
    console.log("Connected");
    ws.send("Hello from " + navigator.userAgent);
  };

  $("#new-message").bind("submit", function(event) {
    event.preventDefault();
    ws.send($("#message-text").val());
    $("#message-text").val("");
  });
});

We connect to the server on port 8080 (the port we listened to in the server) and implement callbacks for when the connection is established, when a message arrives, and when the connection is closed.

We also add an event handler for sending a new message when the user submits a form.

This code only supports modern browsers. There are projects that can be used to support older browsers via a Flash implementation.

To start serving the browser client on port 8000, run python -m SimpleHTTPServer from the directory with the HTML and JS file.

iOS client

To build the iOS client you need a Mac and the Apple developer tools (Xcode) installed. To run it on an actual device (and not the simulator), an Apple developer program membership is required.

For iOS, we use the websocket client implementation SocketRocket. The easiest way to include the library is via Cocoapods. This is what our Podfile looks like:

platform :ios, "7.0"

pod "SocketRocket"

If you haven't got Cocoapods installed, run gem install cocoapods and pod setup. Then run pod install from the iOS directory with the Podfile, and we're good to go.

The relevant code is in ViewController.m. To connect to the websocket server:

- (void)connectWebSocket {
  webSocket.delegate = nil;
  webSocket = nil;

  NSString *urlString = @"ws://localhost:8080";
  SRWebSocket *newWebSocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:urlString]];
  newWebSocket.delegate = self;

  [newWebSocket open];
}

Replace localhost with the relevant hostname if not running the simulator on the same computer that runs the websocket server.

Then we implement the SRWebSocketDelegate protocol:

- (void)webSocketDidOpen:(SRWebSocket *)newWebSocket {
  webSocket = newWebSocket;
  [webSocket send:[NSString stringWithFormat:@"Hello from %@", [UIDevice currentDevice].name]];
}

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
  [self connectWebSocket];
}

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
  [self connectWebSocket];
}

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
  self.messagesTextView.text = [NSString stringWithFormat:@"%@\n%@", self.messagesTextView.text, message];
}

Note that this is very similar to the Websockets browser Javascript API.

Here is how to send a new message:

- (IBAction)sendMessage:(id)sender {
  [webSocket send:self.messageTextField.text];
  self.messageTextField.text = nil;
}

The remaining code in the iOS project is mainly for dealing with resizing views when showing or hiding the keyboard. The app targets iOS 7.0 and is not optimized for iPad.

Android client

The Android app is built using Android Studio.

For Android we will use the client library Java WebSockets. Since we're using Android Studio, the easiest way to include the code from Maven is by listing it in the gradle dependencies in build.gradle:

dependencies {
  compile "org.java-websocket:Java-WebSocket:1.3.0"
}

Gradle will take care of downloading it and making it available to the project the next time we build.

The relevant code for interacting with the websocket server is in MainActivity.java. To connect to the websocket server:

private void connectWebSocket() {
  URI uri;
  try {
    uri = new URI("ws://websockethost:8080");
  } catch (URISyntaxException e) {
    e.printStackTrace();
    return;
  }

  mWebSocketClient = new WebSocketClient(uri) {
    @Override
    public void onOpen(ServerHandshake serverHandshake) {
      Log.i("Websocket", "Opened");
      mWebSocketClient.send("Hello from " + Build.MANUFACTURER + " " + Build.MODEL);
    }

    @Override
    public void onMessage(String s) {
      final String message = s;
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          TextView textView = (TextView)findViewById(R.id.messages);
          textView.setText(textView.getText() + "\n" + message);
        }
      });
    }

    @Override
    public void onClose(int i, String s, boolean b) {
      Log.i("Websocket", "Closed " + s);
    }

    @Override
    public void onError(Exception e) {
      Log.i("Websocket", "Error " + e.getMessage());
    }
  };
  mWebSocketClient.connect();
}

Make sure to change websockethost to whichever address hosts the websocket server.

And to send a new message:

public void sendMessage(View view) {
  EditText editText = (EditText)findViewById(R.id.message);
  mWebSocketClient.send(editText.getText().toString());
  editText.setText("");
}

The Android app targets Android 4.0+. It requires the android.permission.INTERNET permission to connect to the websocket server.

Hopefully this example illustrates that using Websockets from native mobile apps is a viable alternative, especially if there is a web browser client consuming the same API.

Again, all the example code above is available at https://github.com/elabs/mobile-websocket-example. If you clone that repo you should have everything you need to build and run the server and all three clients.

Jan

The Year 2013 — A Summary


Every December, I write a recap of the year that’s gone. I’m a couple of days late this time, but I’d still like to write about some of our highlights from 2013.

Need For Speed™ Network

2013 was dominated by our biggest and most ambitious project yet: Need For Speed™ Network for our new clients Ghost Games and EA. We had pretty much the full team working on this project for most of the year. We’re not completely done with it yet, and we’ll have more to say when we’re finished. In the mean time, check out the promo video for the app.

ProjectPuzzle

Our own product ProjectPuzzle has been left mostly unattended since we launched it in 2012. We had several new customers sign up during 2013 though, and we received lots of great feedback from people who tried it out. We’ve started working on the next version of ProjectPuzzle, and I’m really looking forward to sharing the progress of that with you in the coming months.

Nordic Ruby

The 4th annual Nordic Ruby was the best one yet. It was probably also the last one, in a way. We’re changing things a bit for 2014.

I wrote a blog post about Nordic Ruby 2013 with lots of great photos and video. Check it out if you haven’t already.

Part of the team at Nordic Ruby 2013

Anders T

At the end of November we said goodbye to Anders Törnqvist. Anders was one of the original 4 team members at Elabs, and after 5 great years here he wanted to try switching from consulting to working in a product company. We wish him the best of luck with his new job at PugglePay.

Anders Törnqvist

What’s next?

Right now we’re working hard on finishing the last pieces of the Need For Speed™ Network project, and after that we’re looking for new client projects. If you have something you think we can help with, please get in touch.

Other than client work, we’re also very excited about getting to work on the next versions of ProjectPuzzle and Nordic Ruby.

Here’s to 2014.

/ CJ

Jun

Nordic Ruby 2013


Earlier this month, we held the fourth edition of Nordic Ruby, the conference we organise every year. Just like last year we held it at Hasseludden Yasuragi, a beautiful Japanese-style spa in the Stockholm archipelago.

Terrace

I couldn't be happier with the way the conference turned out this year. We had some incredible talks from our fantastic speakers, and I had a wonderful time meeting old friends and making new ones.

CJ on stage

If you want to see more of what Nordic Ruby was like this year, you'll find slides, notes, blog posts and photos in the coverage section of our Lanyrd page.

Some standout links that you'll definitely want to check out:

Speaking of what Nordic Ruby is all about, I think this year's conference showed that it's not about Ruby in any case. It's never been really, but we haven't done a good job communicating that. That's changing.

Teppanyaki

Nordic Ruby will be back next year, but it won't be called Nordic Ruby any more. The name of the conference will be different, but the feeling of it will stay the same. If you want to keep up with our announcements about it, make sure you follow @nordicruby on Twitter.

See you next year!

Nordic Ruby 2013 from Alexander Lang on Vimeo.