Discussion with a Java switcher

For the past 6 months, I have had regular discussions with an experienced Java developers who switched to Ruby a couple years ago. Names have been changed to protect the guilty but to help you understand my friend ‘Duke’ better, you need to know that he has been a developer for 10 years and lead many complicated, high traffic projects. He recently released two Ruby on Rails projects and he has been fighting with performance issues and scalability challenges.

Duke is a happy Ruby developer but he sometimes has a hard time understanding why things are done in a certain way in the Ruby community. Here are some extracts from our conversations. My answers are only based on my own experience and limited knowledge. They are probably not shared by the entire  community, feel free to use the comment section if you want to add more or share your own answers.

Threads / Concurrency

Duke: Why does the Ruby community hate threads so much. It seems to be a taboo discussion and the only answer I hear is that threads are hard to deal with and that Ruby does not have a good threading implementation. What’s the deal there? If you want concurrent processing, threads are important!

Me: This is a very good question and I think there are two main reasons why threads and thread safety are not hot topics in the Ruby world. First, look at Ruby’s main implementation itself. If you are using an old version of Ruby (pre Ruby 1.9) you don’t use native threads but green threads mapping to only 1 native thread. Ilya has a great (yet a bit old) blog post explaining the difference, why it matters and also the role and effect of the Global Interpreter Lock (GIL). Also, even though Rubyists like to say that they live in the edge, most of them still use Ruby 1.8 and therefore don’t really see the improvements in Ruby 1.9 nor yet understand the potential of fibers.

The other part of the explanation is that the Rails community never really cared until recently. Yehuda Katz recently wrote a good article on thread safety in Ruby and if you read his post and Zed Shaw’s comment you will understand a bit better the historical background. As a matter of fact, the current version of Rails is not multi-threaded by default and developers interested in handling concurrent requests in one process should turn on this option. Thread safety appeared for the first time in Rails 2.2 but from what I saw, most people still don’t enable this option. There are many reasons for that. First, enabling thread safety disables some Rails features like automatic dependency loading after boot and code reloading. A lot of Rails developers take these two features for granted and don’t understand that they are technically “hacks” to make their lives easier. I do believe a lot of Rails developers don’t understand how threads, thread safety, concurrency, blocking IO and dependencies work. They care about getting their app done and meet their deadlines. They usually use and know Rails without paying too much attention to how Rails extends Ruby. Imagine what would happen if their code wasn’t thread safe and Rails wasn’t not using a global lock by default. Now you see why things are not exactly as you expect and also why some Rubyists are getting excited about new projects like node.js which takes a different approach.

The other thing to keep in mind is that at least 90 to 95% of the Rails apps out there don’t get more than a dozen requests/second (a million requests/day). You can scale that kind of load pretty easily using simple approaches like caching,  optimize your DB queries, load balancing to a couple servers. As a matter of fact, compared to the amount of people using Rails on a daily basis, only a very little amount of people are struggling with performance and scalability like you do. This is not an excuse but that explains why these people don’t care about the things you care about.

Rails is slow

Duke: I don’t understand why Rails developers are not more concerned about the speed/performance penalty induced by Rails.

Me: Again, Rails is fast enough for the large majority of developers out there. As you know, as a developer you have to always make compromises. The Rails team always said that development time is more expensive than servers and therefore the focus is on making development easier, faster and more enjoyable. However to get there, they have to somewhat sacrifice some performance. What can be totally unacceptable for you is totally fine for others and your contribution is always welcome. This is probably the root cause of the things you don’t like in Rails. Rails was built for startups, by startup developers and you don’t fall in this category. People contributing new features and fixes are the people using Rails for what it is designed to do. There is no real ‘Enterprise’ support behind Rails and that might be why you feel the way you feel. Since you find yourself questioning some key Rails conventions and you are struggling with missing features, it looks  to me that you chose the wrong tool for the job since you don’t even use 70% of the Rails features and are dreaming of things such 3 tier architecture. Sinatra might be a better fit for you if you want lower level control, less conventions and less built-in features.

Object allocation / Garbage Collection

Duke: I recently read that Twitter was spending 20% of its request cycles in the GC, am I the only finding that concerning?

Me: Most people don’t realize how the GC works and what it means to allocate objects since Ruby does that automatically. But at the same time, most of these people don’t really see the affect of the Garbage Collection since they don’t have that much traffic or they scale in ways that just skips their Ruby stack entirely. (Or they just blame Ruby for being slow)

If you are app deals with mainly reads/GET requests, using HTTP caching (Rails has that built-in) and something like Varnish/Rack-cache will dramatically reduce the load on your server apps. Others don’t investigate their issues and just add more servers. As mentioned in a previous post, some libraries like Builder are allocating LOTS more objects than others (Nokogiri), use the existing debugging tools to see where your object allocations occur and try to fix/workaround these. In other words, Ruby’s GC isn’t great but by ignoring its limitations, we made things even worse. My guess is that the GC is going to improve (other implementations already have better GCs) and that people will realize that Ruby is not magic and critical elements need to be improved.

Tools

Duke: I really have a hard time finding good tools to help scale my apps better and understand where I should optimize my code.

Me: It is true that we area lacking tools but things are changing. On top of the built-in tools like ObjectSpace, GC::Profiler, people interested in performance/debugging are working to provide the Ruby community with their expertise, look at memprof and ruby-debug for instance. Of course you can also use tools such as Ruby-prof, Kcachegrind, Valgrind and GDB. (1.9.2 was scheduled to have DTrace support but I did not check yet). Maybe you should be more explicit about what tools you miss and how we could solve the gap.

ActiveRecord

Duke: ActiveRecord doesn’t do what I need. How come there is no native support for master/slave DBs, sharding, DB view support is buggy,  suggested indexes on queries is not built-in and errors are not handled properly (server is gone, out of sync etc..)?

Me: You don’t have to use ActiveRecord, you could use any ORM such as Sequel, DataMapper or your own. But to answer your question, I think that AR doesn’t do everything you want because nobody contributed these features to the project and the people maintaining ActiveRecord don’t have the need for these features.

What can we do?

We, as a community, need to realize that we have to learn from other communities and other programming languages, this kind of humorous graph is unfortunately not too far from reality.

Bringing your expertise and knowledge to the Ruby community is important. Looking further than just our own little will push us to improve and fulfill the gaps. Let the community know what tools you are missing, the good practices you think we should be following etc…

Take for instance Node.js, it’s a port of Ruby’s EventMachine / Python’s twisted. There is no reasons why the Ruby or Python versions could not do what the Javascript version does. However people are getting excited and are jumping ship. What do we do about that? One way would be to identify what makes node more attractive than EventMachine and what needs to be done so we can offer what people are looking for. I asked this question a few weeks ago and the response was that a lot of the Ruby libraries are blocking and having to check is too bothersome. Maybe that’s something that the community should be addressing. Node doesn’t have that many libraries and people will have to write them, in the mean time we can make our libs non-blocking. Also, let’s not forget that this is not a competition and people should choose the best tool for their projects.

Finally, things don’t change overnight, as more people encounter the issues you are facing, as we learn from others, part of the community will focus on the problems you are seeing and things will get better. Hopefully, you will also be able to contribute and influence the community to build an even better Ruby world.

,

14 Comments

Ruby object allocation & why you should care

Recently I was tasked with finding how to optimize a web application with heavy traffic. The application (a Rails 2.3.x app) gets about 3 million requests per hour and most of these requests cannot really be easily cached so they go through the entire stack.

This is probably not the case of most web apps out there. None the less, my findings my help you understand Ruby better and maybe think differently about memory management.

This is certainly not an advanced GC blog post, I will try to keep it as simple as possible. My goal is to show you how Ruby memory allocation works and why it can affect your app performance and finally, how can you avoid to allocate to many objects.

Ruby memory management.

Rubyists are quite lucky since they don’t have to manage the memory themselves. Because developers are lazy and Matz developed his language for people and not machine, memory is managed “magically”. Programming should be fun and managing memory isn’t really considered fun (ask video game developers or iOS programmers ;) ).

So in Ruby, the magical memory management is done by a Garbage Collector. The GC’s job is to run and free objects that were previously allocated but not used anymore. Without a GC we would saturate the memory available on the host running the program or would have to deallocate the memory manually. Ruby’s GC uses a conservative, stop the world, mark-and-sweep collection mechanism.  More simply, the garbage collection runs when the allocated memory for the process is maxed out. The GC runs and blocks all code from being executed and will free unused objects so new objects can be allocated.

Joe Damato did a great talk on that matter during last RailsConf

Garbage Collection and the Ruby Heap

The problem is that Ruby’s GC was not designed to support hundred thousand objects allocation per second. Unfortunately, that’s exactly what frameworks like Ruby on Rails do, and you might contribute to the problem too without even knowing it.

Does it really matter?

I believe it does. In my case improving the object allocation means much better response time, less servers, less support and less headaches. You might think that servers are cheaper than developers. But more servers mean more developer time spent fixing bugs and more IT support. That’s why I think, memory management is something Ruby developers should be aware of and should take in consideration, especially the ones writing frameworks, libraries or shared code.

I am using Ruby 1.9 so I could not profile my Rails 2.x app using memprof, instead I wrote a simple and basic middleware that keeps track of the memory allocation/deallocation and GC cycles during a web request (Ruby1.9 only). One of my simple Rails2 actions (1 DB call, simple view) is allocating 170,000 objects per requests. Yes, you read right: 170k objects every single request. At 3 million requests/hour, you can imagine that we are spending a LOT of time waiting for the GC. This is obviously not 100% Rails fault as I am sure our code is contributing to the problem. I heard from the memprof guys that Rails was allocating 40k objects. I decided to check Rails3.

After warming up, a basic Rails3 ‘hello world’ app clocks at about 8,500 objects allocated per request, forcing the GC to run more or less every 6 requests. On my machine (mac pro) the GC takes about 20ms to free the objects. A Rack ‘hello world’ app clocks at 7 objects per request and a Sinatra app at 181 objects. Of course you can’t really compare these different libraries/frameworks but that gives you an idea of the price you pay to get more features.

One thing to remember is that the more objects you allocate, the more time you “lose” at code execution. For more developers, it probably doesn’t matter much, but if you should still understand that concept especially if you decide to contribute to the OSS community and offer patches, libraries, plugins etc…

What can I do?

Be aware that you are allocating  objects, for instance something as simple as 100.times{ ‘foo’ } allocates 100 string objects (strings are mutable and therefore each version requires its own memory allocation).

Make sure to evaluate the libraries you use, for instance switching a Sinatra XML rendering action from Builder to Nokogiri XML Builder saved us about 12k object allocations (Thanks Aaron Patterson). Make sure that if you are using a library allocating a LOT of objects, that other alternatives are not available and your choice is worth paying the GC cost. (you might not have a lot of requests/s or might not care for a few dozen ms per requests). You can use memprof or one of the many existing tools to check on the GC cycles using load tests or in dev mode. Also, be careful to analyze the data properly and to not only look at the first request. Someone sent me this memory dump from a Rails3 ‘hello world’ with Ruby 1.8.7 and it shows that Rails is using 331973 objects.  While this is totally true, it doesn’t mean that 330k objects are created per request. Instead that means that 330k objects are currently in memory. Rubygems loading already allocate a lot of objects, Rails even more but these objects won’t be GC’d and don’t matter as much as the ones allocated every single request. The total amount of memory used by a Ruby process isn’t that important, however the fluctuation forcing the GC to run often is. This is why my middleware only cares about the allocation change during a request. (The GC should still traverse the entire memory so, smaller is better)

The more object allocation you do at runtime/per request, the more the GC will need to run, the slower your code will be. So this is not a question of memory space, but more of performance. If your framework/ORM/library/plugin allocates too many objects per request maybe you should start by reporting the problem and if you can, offer some patches.

Here are some hints about memory allocation:

Creating a hash object really allocates more than an object, for instance {‘joe’ => ‘male’, ‘jane’ => ‘female’} doesn’t allocate 1 object but 7. (one hash, 4 strings + 2 key strings) If you can use symbol keys as they won’t be garbage collected. However because they won’t be GC’d you want to make sure to not use totally dynamic keys like converting the username to a symbol, otherwise you will ‘leak’ memory.

Looking at a GC cycle in the Rails3 hello world example shows what objects get deallocated:

GC run, previous cycle was 6 requests ago.

GC 203 invokes. (amount of cycles since the program was started)
Index   1

Invoke Time(sec)   25.268

Use Size(byte)   4702440

Total Size(byte)   7307264

Total Object   182414

GC Time(ms) 22.35600000000204090611

## 56322 freed objects. ##
[78%] 44334 freed strings.
[7%] 4325 freed arrays.
[0%] 504 freed bignums.
[1%] 613 freed hashes.
[0%] 289 freed objects.
[5%] 3030 freed parser nodes (eval usage).

I did not list all the object types but it’s pretty obvious that the main issue in the case of Rails is string allocation. To a certain extend the allocated arrays and the runtime use of eval are not helping either. (what is being eval’d at runtime anyway?)

If you use the same string in various place of you code, you can “cache” them using a local var, instance variable, class variable or constant. Sometimes you can just replaced them by a symbol and save a few allocations/deallocations per request. Whatever you do tho, make sure there is a real need for it. My rule of thumb is that if some code gets exercised by 80% of the requests, it should be really optimized and avoid extra allocations so the GC won’t slow us down.

What about a better GC?

That’s the easy answer. When I mentioned this problem with Rails, a lot of people told me that I should use JRuby or Rubinius because their GC were much better. Unfortunately, that’s not that simple and choosing an alternative implementation requires much further research and tests.

But what annoys me with this solution is that using it is not solving the issue, it’s just working around it. Yes, Ruby’s GC isn’t that great but that’s the not the key issue, the key issue is that some libraries/frameworks allocate way too many objects and that nobody seems to care (or to even know it). I know that the Ruby Core Team is working on some optimizations and I am sure Ruby will eventually get an improved GC. In the meantime, it’s easy to blame Matz, Koichi and the rest of the core team but again, it’s ignoring that the root cause, totally uncontrolled memory allocation.

Maybe it’s time for us, Rubyists, to think a bit more about our memory usage.

15 Comments

Au Revoir Rails community

Time really flies!

Back in December 2005, Ruby on Rails 1.0 was released to the masses. I remember that was when I first got interested in Rails. Six months later, I was doing Rails development full time.

Rails pushed me to contribute to the project, to write plugins, to improve my Ruby knowledge, to release gems and to become a better engineer overall. I then joined the Merb project, focusing on problems I was facing in the various client projects I had back then.

The competition between Rails and Merb turned into a constant confrontation, splitting the Ruby community into two camps. A resolution was later achieved by merging the two teams and focusing our energy on Rails 3. This is how I became a part of the Activism team with Gregg and Ryan. In this new role I was given the opportunity to meet lots of different people from various backgrounds and different communities. I really had a lot of fun.

However, things have changed for me. I won’t be at Rails Conf 2010 because in a few weeks I will become a father for the first time. And with that, an obvious priority shift. My day job working on Playstation games is also quite time consuming and the little free time I manage to get to work on my own projects is spent on my MacRuby book. The disconnect between the Rails community and myself is probably more evident now than ever. The challenges encountered by most Railists are so different from the ones I face daily that I think others would do a much better job than I at advocating for Rails. So this is why I believe it’s time for me to step away from the Rails community, kick back and relax (and get ready to change a lot of diapers).

This is an “au revoir“, not an “Adieu“. I will continue to keep an eye on Rails 3 and the fast growing ecosystem.

I will still be writing Ruby for a living and will hopefully keep contributing to the projects I use. And I plan to keep on attending to Ruby conferences around the world just as soon as my kid is old enough to travel with me ;)

Finally, with the imminent release of Rails 3, I hope to see even more people stand up and advocate for Ruby on Rails the way Gregg Pollack, Ryan Bates and many others have done so far.

13 Comments

Writing an open licensed book

To celebrate last week’s release of MacRuby 0.6, O’Reilly and I started publishing the draft of my MacRuby book online: http://macruby.labs.oreilly.com/

I started thinking about working on “MacRuby: The Definitive Guide” last year when I realized that the project had a great future but there was a serious lack of documentation. With the support of the MacRuby team, I worked on a table of contents and a pitch. The next step was to decide what we wanted to do with the book.

I know a lot of technical book authors and most of them will tell you the same thing: if you think that you are going to make money writing a book, you are wrong. Even if your book sells well, because of the time invested in writing the book, you are probably better off doing consulting work and charging by the hour.

So since day one, I knew that this project would not make me rich. The goal was to share knowledge not to reimburse my mortgage or save California from bankruptcy. While publishing a web book is great, distribution is quite limited, especially if you try to reach people outside of your network. That’s why I decided to start talking to a few publishers. Most publishers I talked to were interested in working on the book, however they were not really keen on publishing a Creative Commons Attribution-Noncommercial-No Derivative licensed book.

Let me explain why I think releasing technical books under a CC license is important. As you might know (or have figured out by now), I am not a native English speaker. I actually learned my first English words thanks to the computer my dad had at home. The problem when you don’t live in an English speaking country and you want to learn about the cutting edge technology is that you have to understand English.  Thanks to the Internet, learning and practicing English is now much easier that it used to be. However, if you want to have access to books, most of the time you have to wait until someone translates the book and publishes it in your country or you have to manage to get an English version delivered to your country. This is often a pain because of national credit card limitations, international delivery restrictions etc… If you manage to find a way to get a copy, the book ends up costing a lot of money.

What does that mean in practice? Most of the technical books are first available in the English speaking western world, then slowly translated and/or distributed around the world. By the time you get a legal copy in Bolivia, Algeria or Vietnam, a new edition is probably out in the US probably because the technology evolved. Maybe that explains some of the book piracy worldwide?

Think about it for a minute: knowledge is power and time is money. And what do we do? We delay knowledge distribution. This is why I am a big fan of the Khan Academy and its awesome free online courses.

Turns out O’Reilly shares my vision and has already published a lot of books under various open licenses: http://oreilly.com/openbook/ I was also interested in publishing the content of my book ASAP so people could access it right away even though there would be lots of typos and missing content. This is also something O’Reilly has already done with the CouchDB and the Scala books.

Talking with Jan Lehnardt about his experience working with O’Reilly on the ‘CouchDB: The definitive guide’ book, I realized that we seem to have some shared interests. I contacted Jan’s editor and we decided to start working on the MacRuby book. The book will be available later on in all the usual commercial formats and I hope people will show their support so O’Reilly will be encouraged in their choice to continue publishing CC licensed book. At the end of the day, purchasing a CC licensed book helps supporting the authors, the publishers but also all the people who can’t have access to the latest technical books.

Finally, working on a book is not an easy thing, especially when you have to write it in a language that’s not yours. But I have to say that the community support has been amazing. Even John Gruber sent a fireball my way. And since the announcement was made, I have received a lot of comments, tweets, emails etc… It is very encouraging and it gives me the motivation needed to work on the book after a long work day.

, ,

4 Comments

I did it wrong

The Ruby community is a well known for at least two things: being passionate and being arrogant .
Two characteristics that often go together but I am not going to defend or justify anything in this post, instead I will try to reflect on my own experience and will share with you my own view point.

Very much like the Ruby community, I am also quite passionate and can be arrogant at times. A few months back I was in Brazil for RailsSummit and I was chatting with David Chelimsky after a nice evening with the RailsSummit attendees. I was thinking about how cool it was to have people from various non-Ruby communities to come to a Ruby community and share their experience and knowledge while observing the ways we do things with Ruby.

David and I got to talk about technical evangelism, how RSpec became very popular, the whole Merb vs Rails situation which turned into Rails3, as well as MacRuby and Apple. I was interested by the fact that I couldn’t remember David ever saying something bad about test/unit or trying to tell others they were doing it wrong. Instead, he has always tried showing why people might be potentially interested by RSpec.

As an early RSpec adopter, I often thought that people were wrong not to use the solution that I thought was the best. As part of the Merb ‘propaganda’, we spent a lot of time comparing Merb with Rails and showing why Merb might be better for you and why you were doing it wrong if you would fit in Merb’s target and still use Rails.

Even before that, I remember thinking that if you were not using Ruby, you were doing it wrong. PHP & Java developers were, for me, just developers who did not know any better (and I thought that Python-ers were just too lazy to learn a “better” language that takes OOP seriously ;) ).


Since then, things have changed. I have gotten involved with other projects, met different people and maybe, just maybe, matured a little bit. Going back to the discussion I had with David, he pointed out to me how often people talk about a piece of technology or an idea to just quickly conclude: “it sucks” and it has got even worse lately with the ‘you’re doing it wrong ‘ meme.

Basically, we judge people’s actions without knowing them or even having a clue about the problem they are facing and we just tell them that if they don’t do like us, they are wrong. If they are not using this plugin or this gem, they are doing it wrong, and if they are using this other one that sucks, they are also doing it wrong. Also, be careful, something that’s hot today will probably turn out to be ‘the suck’ soon enough, keep up with what the cool kids tweet about ;)

But of course, this is something human and much bigger than the Ruby community. Look at the whole SQL/NoSQL pseudo fight and you will notice the same attitude. Look at the editors war, look at the OS war or even look at the TV with shows like ‘Marriage Ref‘ making money off of people wanting to prove their partner that he/she is doing it wrong. But that’s also the root problem of most religion wars and even the motivation for some people to go ‘invade/colonize’ other countries to eventually force their world vision upon them.

I realize the irony of writing of blog post to tell my readers that telling others that they are doing it wrong is, in itself, fundamental wrong, but maybe next time you think something sucks or is totally wrong, you might want to try to understand the motivation behind why some people decided to go this way. I know I will personally try harder.

16 Comments

How and why I joined the “suit people”

It is now official: I have traded my freedom & home office for a job title, an Aeron chair in a cubicle and a 401K.

I received my new employee package and, in less than a week, I will officially become a full-time employee at  SCEA (Sony Computer Entertainment America).

I’m going to work in the PlayStation department, working on PS3, PS2 and PSP game titles developed by various game studios.

Why ‘o why?

Why leave behind a happy life of indie contracting to join corporate America?

For many reasons actually:

  • A Team

Being a consultant I have been working with other independent consultants and existing teams. Nonetheless, I really miss being part of a stable team which grows together and learns from each other as we go through new projects and maintain old ones.

  • Long term plan

As a consultant, I usually start projects or “rescue” existing projects. I work on them for a little while and then move on. It’s exciting and rewarding but you don’t really pay the consequences of your mistakes. You usually don’t have to maintain the code you wrote and you rarely deal with the mistakes you made.

It sounds good, nobody likes to maintain the crappy awesome code they wrote 2 years ago and most developers love working on new stuff. But at the same time, to become a better engineer you need to learn from you mistakes and assuming responsibility for your bad decisions is part of the process.

It might sound weird, but I’m actually excited to work on long term projects and feel some sort of ownership over the projects. Having to support games for many years means that I’d better not mess up the implementation. And if I do, I hope I’ll quickly learn from my mistakes.

  • Avoiding burn out

There is no secret: when you are passionate about what you do, you have a hard time stopping and taking a break. I’m a recovering workaholic and it’s really hard for me to say no when I’m presented the possibility to work on interesting projects. I love what I do and I keep writing code even after I’m done with client work.

The problem is that this can start me on the slippery slope to isolating myself from friends, family and people who don’t share the same passion. I’m really lucky that my wife is a geek and loves hanging out at conferences, looking at code and playing with my buggy prototypes. But still, I spend too much time “playing” with my computer and I just can’t manage my free time wisely.

Having a full time position will hopefully help me put boundaries and will hopefully teach me to disconnect from work.

  • Exciting projects

Hey, let’s be honest, how many geeks do you know don’t want to work in the video game industry? By the way, if you don’t have a PS3, they are now at $299 and on top of getting an awesome console you get a blue ray player! (And no, I do not receive any bonuses or commissions for mentioning the console or promoting it in my blog. I had to pay for my own like everyone else.)

Corporate America? Are you going to write Java now?

No, I’m mainly going to stick to the language I love: Ruby.
From time to time I will probably use other languages here and there, but that usually makes me love Ruby even more. The reality is that Ruby’s power and flexibility seem to be appreciated by SCEA, which makes sense when you have tight deadlines and a lot of new technologies to deal with. Ruby is a perfect match!

As you can guess, I can’t go into any detail about how and why Sony uses Ruby, but let me just say that while games are still usually written in C++, they are becoming more and more interactive and need to communicate with game servers where some logic operates. Game players also need to interact with other gamers as well as check their gaming progress online, as well as the progress of the players around them etc… Basically, outside of the game engine and the console SDK, there is a lot of potential for Ruby.

Coming back to Corporate America, I have to say that I’ve known my future manager for a few years now. He’s always been a fervent Ruby advocate and has introduced lots of teams to the happiness of Ruby & Rails development. He’s also a great developer who’s contributing patches to major projects and has a bunch of cool stuff on github. To give you an idea, my job description mentions Rails, Merb, Sinatra, CouchdB, MongoDB, Redis, AWS. All these Ruby technologies are actually already used in production or are being seriously evaluated.

I’m also really looking forward to join the existing team. I know I’m going to love working with a bunch of awesome developers coming from various backgrounds.

Those who know me, know that I’m not a morning person. And while your typical office job is categorized as ’9-5′, don’t feel too bad for me. I will be joining the video game product department, and morning people are rather rare in these kinds of groups ;)

Conclusion

I’m really excited about this opportunity. For me, it is proof again that the Ruby revolution took place and that the Enterprise is evolving. Of course, time will tell if I am right, but I am quite confident.

Also, Sony is always looking for new, talented people who want to push the entertainment world to the next level. Feel free to keep in touch with me if you are interested in joining the fun.

, , ,

42 Comments

Undo/Redo in MacRuby

As I’m working on my upcoming O’Reilly MacRuby book, I’m writing quite a lot of example code. I have spent the last few weeks digging through most of the Foundation framework classes to hopefully make Cocoa more accessible to Ruby developers.

In some instances things might look quite weird to someone new to Cocoa in some cases, things seem almost too easy. Here is an example implementing a undo/redo functionality using Foundations’ NSUndoManager.

framework 'Foundation'
class Player
  attr_accessor :x, :y
 
  def initialize
    @x = @y = 0
  end
 
  def undo_manager
    @manager ||= NSUndoManager.alloc.init
  end
 
  def left
    undo_manager.prepareWithInvocationTarget(self).right
    @x -= 1
  end
 
  def right
    undo_manager.prepareWithInvocationTarget(self).left
    @x += 1
  end
end

Which you can use as such:

 
>> lara = Player.new
=> <Player:0x200267c80 @y=0 @x=0>
>> lara.undo_manager.canUndo
=> false # normal since we did not do anything yet
>> lara.left
=> -1
>> lara.x # -1
=> -1
>> lara.undo_manager.canUndo
=> true # now we can undo, so let's try
>> lara.undo_manager.undo # undo back to initial position
=> #<NSUndoManager:0x200257560>
>> lara.x
=> 0
>> lara.undo_manager.canUndo
=> false # we can't anymore which makes sense 
>> lara.undo_manager.canRedo
=> true # however we can redo what we just undone
>> lara.undo_manager.redo # redo to before we called undo
=> #<NSUndoManager:0x200257560>
>> lara.x
=> -1

The above example was tested in macirb but as you can see, actions can be undone and redone very very easily. This is just a quick preview of what you can do using Ruby + Cocoa and hopefully it will give you some cool ideas to implement.

, , , ,

9 Comments