Thursday, August 8, 2013

Strategy pattern in Ruby - x 4

One of my weaknesses as a developer is that I don't really know design patterns as well as I should. I use some of them frequently (Builder, Factory, Adapter, Decorator) but I've never used some of the others, and it caused me some pain the other day. So I'm going through the various design patterns and trying to implement them in various ways in Ruby.

I started playing this evening with the Strategy pattern. The most obvious implementation of the strategy pattern in Ruby is just using modules, like so:

Monday, August 5, 2013

Kul vs Rails

After having used it for a while, I think the time has come to kill deprecate Kul. Building it has taught me a great deal about many things, not least of which is just how complex Rails is.

The big sticking point I had with Rails is the router. Everything else in Rails is workable, and there's no reason to discard all of that code just to fix the router. I'm sure that I can convince rails to look in the views folders for the controller, and skipping ActiveRecord is simple and well-documented.

What I discovered the other day is that the Rails router can delegate straight to a Rack application. Which means that it's just a single line in the routes.rb (and an entire rack implementation I suppose) that will put my nifty routing / controller DSL plan in place.

Like Kul, this will probably be more of an experiment for learning purposes than a serious project. The Rails router and controllers really do a lot of work, and it's probably not a good idea to hijack them in production. But it should be fun to play with.

First thing is to switch Twitarr over to Rails. Unfortunately at this point I'm busy trying to learn Ember.js, which is not a trivial web framework. The value is there, but the documentation makes it very difficult.

Monday, July 22, 2013

Ember and Ember Data

I've been modding my version of Twitarr and checking to see if it works in Ember.Js.

The killer feature in Ember is the router, although the integration with templates (and being able to break your UI into pieces) is a close second in the feature race. As much as I enjoy working with KnockoutJS, it doesn't implicitly have those features. Sure, you could integrate a template engine such as Mustache and use some patterns to break up your javascript, but why do all that work when someone has already built the framework for you.

I've had two basic problems with Ember so far. First is the documentation. It's bad. The Ember team acknowledges how bad it is, but it's still just... bad. It doesn't help that MVC used for webapps bears no resemblance to MVC for client-side code. (Technically the MVC pattern used in Ember is closer to the original ideal)

But it is workable. And when it works, it's honestly amazing. I spent the money on the tutorial from PeepCode - most of the information I had already gleaned by working the Ember tutorial, but there were some things that the Peep guys clarified. It's a good tutorial if you're just starting in Ember.

The second problem is Ember Data. The Ember tutorial as well as the PeepCode tutorial will lead you to use Ember Data, and it is officially Not Done Yet. It also has some serious logistical problems in my mind. One pattern I often use is to have users input data into a form, then send that data to the server to be enriched and sent back. Ember Data has validation, but that's a simple binary save / no save. There's no simple way (that I've found) to be able to modify a record on the server side and update that data back to the client.


It's particularly frustrating in a microblog where I want to timestamp the post server side and add the username server side (I suppose I could check that the username for a post matches the session, but why? - then I'd have to write code to close a security hole that I don't need to open). Rule number one of webapps is to never trust data from the client, and validation doesn't always fit the bill.

Then there's refreshing the data, and having multiple arrays containing the same model type but with different parameters - none of it is really enabled with Ember Data. I just couldn't find simple ways of solving the problems I was running into.

Then I ran into this post by Robin Ward which talks about kicking Ember Data to the curb. And the heavens opened and the light showed down. I had looked through the Discourse github and had seen that they weren't using Ember Data, but it helped to have it laid out in black and white.

(Also a great post by Robin is this one that compares Ember and Angular)

So, yeah. Getting rid of Ember Data removes 99% of the roadblocks I'm running into. I assume that the Ember team is basing their documentation on Ember Data to be future-compatible, but I wonder if they're hurting overall adoption. I know that my frustration level was getting to the point where I was questioning Ember as a choice.

Wednesday, May 29, 2013

Redis and Twit-arr

Just experienced my first PEBKAC while using my library - code reloading doesn't work when the server is in production mode.

Over the weekend, I started eating my own dog food where Kul is concerned. Last year, my wife and I went on the Joco Cruise Crazy - and it was awesome. Highly recommended. Cruising is something that IMHO requires friends, and 800+ fellow nerds are a great group of soon-to-be friends to go with.

(I also got to meet John Scalzi - and got to watch Wil Wheaton play Artemis. That's hard to beat, you gotta admit)

Anyway, the group brought along their own server with it's own microblogging instance. And while it was neat and all, it wasn't exactly set up for the cruise. It tended to overwhelm the wifi capacity whenever the entire group was together, and it didn't exactly make the best use of small screens, etc. The concensus was that on the next trip Twit-arr (the microblog) would have its software overhauled.

So over the weekend I started putting together a new version. I started with Kul (of course), and it's helped me to see some of the flaws / weak points in what I'm building. I've already made some changes to the framework based on things that were difficult to use.

I'm using Redis as a backend for the service as well. Redis is awesome, and it's Ruby integration is even more awesome (if that's possible). The installation guide in the quickstart was one of the most complete I've ever used, and if it took me an hour to set Redis up it was only because I was going slowly. Awesome, awesome, awesome.

Basically, I got to mess around with Redis (which I've been wanting to for awhile), use my own framework, and build something that (hopefully) will be of use to a bunch of people.

The code for my new twit-arr instance is up on GitHub, of course. Still in early development but I'm having a blast with it.

Ruby / Sinatra stuff

I had trouble finding this little nugget out there, but it seems that Ruby's require statement is now thread-safe. Looking at the web, it seems that it didn't used to be back in 2009 or so.

load is still not thread-safe. This makes my auto-loading unsafe. Also learned about autoload, which does some similar things to what I'm doing, but is being deprecated because it's unsafe. Which makes sense, as it should have the same problems I'm experiencing.

Also, I couldn't find anything that described what Sinatra did when it was in development mode - there's a few things I found browsing through the source:

  • Sets the error pages to the Sinatra versions
  • Something with the session secret
  • Turns on template reloading
  • Binds only to localhost
  • Turns on showing exceptions
... and that's it.

Sunday, May 26, 2013

Code reloading

For a web framework, code reloading is a crucial feature (especially for a framework designed for rapid development!). Minutes spent waiting for a server to reload add up quickly. Some of that can be mitigated by doing comprehensive unit testing, but there is no replacement for being able to see your code running in situ.

There's a great explanation of code reloading by Konstantin Haase, some of which I actually understand! The rails deep-diving isn't what I'm interested in, but the explanation of code reloading. This is also the link that Sinatra uses to explain code reloading, so I'm not the only person that uses it as a reference.

The bottom line is that if you want true code reloading, you need to actually have a separate Ruby context for each request - which is what Shotgun (or shotgonne if you're a Prachett fan) does behind the scenes. It's the only real way to guarantee that your code reloads.

Initially the way Kul did code reloading was just to re-load the files every time it loaded one. It's both brute-force and has a few problems. In production, you can't reload the entire website from disk for every request, but in development mode it really isn't that big of an issue.

The bigger issue is that I was basically abusing the open nature of ruby classes. Effectively, the load will reopen the class and redefine it from the code in the file. This works well for a few specific things, and badly (or not at all) for others. For example, adding a method would work fine; removing a method would not work at all.

Plus, as much as I justified it, reloading all of the code on every request did bother me.

Today I started replacing the reloading inside of Kul. It's a small improvement, but I think it should help in the long run. There are some limitations, but it should work for 99% of the expected use of the framework. In the other circumstances, you'll just have to restart the server - sorry.

The first thing I wanted to fix was the brute-force nature of the code reloading. That was simple enough - I just keep track of the file date and don't bother reloading the file if it hasn't been modified. I did find out that (at least on Windows) the modified time is only tracked to the second - I'm sure that's fine for almost everyone else but I had to do some jiggery-pokery to trick the unit tests into passing. It was either that or put a one-second sleep in there, and that's just wrong.

The second thing I did was to assume that require statements are not likely in user code. That's probably the most fragile assumption I'm making, but it should cover most of the usages (once I get the models in, at least). As long as all of the code you're using is either:

  1. inside of a library (which shouldn't change during runtime), or
  2. in framework files such as server.rb or controller.rb
then the framework should be able to gracefully handle changes to your code. Basically, the user has to follow the framework's rules as far as naming files and placing code. 



(This is actually the same assumption I was making before, but I made a more conscious decision whereas before it was just incidental)

There are a few limitations even with that big 'ol assumption up there. If you have more than the framework-expected class in the file, you'll be falling back on the original code reloading (i.e. it won't remove methods / constants / etc). Also, any metaprogramming you've done outside of that file will be gone. Basically don't manipulate classes outside of the file.

Also, any instances hanging around will not change their code. That's the one that I think is most likely to cause confusion. Code reloading could also do some really interesting things with class methods, depending on how they're called. And lastly, this code reloading will work horribly in a multi-threaded environment. I think that it would eventually reach a steady-state, but it's hard to say for sure.

At the end of the day, it's not perfect, but it should make development easier, and that's the final goal. It's not for production anyway. The reloading code will be exposed so that if anyone does want to make use of it from their application, they can call Kul::FrameworkFactory.load_class with the class and path, and the framework will handle the reloading.

Tuesday, May 21, 2013

User Interfaces

This is kind of a followup to a post from a couple months ago about rich internet apps.

Today, if you want to build an application that runs on as many systems as possible, the answer is simple - you build a web application. There are other options: you could build a Java app for example. Java runs on so many systems, and you can build it once and the executable runs anywhere.

However, you have to install Java on the client. Many people don't want to do that. And you have to install the application on the client. More people don't want to do that. A non-sandboxed application is a scary thing to install on a system these days.

I feel that there's limited utility in actually trying to build and distribute a Java application. And the market pretty much bears that out - how many Java apps are actually being worked on these days? I can't think of a one. I'm sure there are some out there, but not very many. And they probably have a very limited / controlled distribution channel.

It makes sense if I think about it. In order for it to be a program, it has to have a set of instructions to run. Those instructions need to either be in the language of the machine, or there needs to be another program on that machine to interpret those instructions. Therefore, you have to have something that can interpret your language of choice on the range of machines you want to run on.

It's simple, basic computers 101 - computers run instructions. But it has consequences when trying to build something that can be run across architectures. There has to be an interpreter for that language on the remote machine. That's all there is to it. You need an interpreter.

In the case of Java, the JVM provides that interpreter - from bytecode to machine instructions. But again, Java has too much power - it allows a malicious programmer to execute instructions that are harmful.

There is one interpreter that both runs in a sandbox and has an even bigger install base than Java does: Javascript. Or ECMAScript, if you're so inclined.

This is why web applications are so popular - they have the single largest install base for the sandbox / interpreter that they run. Heck, most modern phones have multiple browsers - take that Java!

(Also, most browsers don't install the ask toolbar along with themselves)

Web apps also have an incredibly rich graphical interface. It's not the most stable between browsers, but having written applications in Win32, MFC, Swing, WPF, Qt, and HTML - I'll take the web any day.

Cross platform, common GUI applications - what's not to like?

(Well, there are quite a few things, but there's quite a few other places to hear that sort of griping.)